From 723e913bccdc579b471903aee8f2e43cfc9f52ab Mon Sep 17 00:00:00 2001 From: Mirela Chirica Date: Wed, 26 Sep 2018 13:00:32 +0300 Subject: [PATCH 1/2] Cellular: AT handler read string up to delimiter or stop tag --- .../framework/AT/athandler/athandlertest.cpp | 27 +++++++++++----- features/cellular/framework/AT/ATHandler.cpp | 31 ++++++++++++++----- 2 files changed, 43 insertions(+), 15 deletions(-) diff --git a/UNITTESTS/features/cellular/framework/AT/athandler/athandlertest.cpp b/UNITTESTS/features/cellular/framework/AT/athandler/athandlertest.cpp index 7a49a70c42..cd08f2759c 100644 --- a/UNITTESTS/features/cellular/framework/AT/athandler/athandlertest.cpp +++ b/UNITTESTS/features/cellular/framework/AT/athandler/athandlertest.cpp @@ -579,7 +579,7 @@ TEST_F(TestATHandler, test_ATHandler_read_string) EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == at.get_last_error()); at.clear_error(); // Device error because empty buffer and attempt to fill_buffer by consume_char('\"') - EXPECT_TRUE(-1 == at.read_string(buf1, 1)); + EXPECT_TRUE(0 == at.read_string(buf1, 1)); // *** 1 BYTE *** at.clear_error(); @@ -599,7 +599,7 @@ TEST_F(TestATHandler, test_ATHandler_read_string) // *** CRLF *** at.clear_error(); - char table3[] = "\r\ns\r\n\0"; + char table3[] = "\r\n,s\r\n\0"; at.flush(); filehandle_stub_table = table3; filehandle_stub_table_pos = 0; @@ -670,13 +670,9 @@ TEST_F(TestATHandler, test_ATHandler_read_string) at.resp_start(); // TO read 1 byte from: "s"OK\r\n -> read " at.read_bytes(buf5, 1); - // TO read max 1 byte from: s"OK\r\n -> read s + // TO read max 1 byte from: s"OK\r\n -> read s + read to stop_tag(OKCRLF) EXPECT_TRUE(1 == at.read_string(buf4, 1 + 1/*for NULL*/)); - // *** Consume " and run into OKCRLF *** - // TO read max 1 byte from: "OK\r\n -> consume " and find stop tag OKCRLF - EXPECT_TRUE(0 == at.read_string(buf4, 1 + 1/*for NULL*/)); - // *** Try to read after stop tag was found *** // stop tag found do not read further EXPECT_TRUE(-1 == at.read_string(buf4, 1 + 1/*for NULL*/)); @@ -706,7 +702,7 @@ TEST_F(TestATHandler, test_ATHandler_read_string) mbed_poll_stub::revents_value = POLLIN; mbed_poll_stub::int_value = 1; at.resp_start("s"); - // TO read from buffer having only " -> consume " -> trying to read when nothing in buffer + // TO read from buffer having only " -> trying to find delimiter or stop_tag(OKCRLF) EXPECT_TRUE(-1 == at.read_string(buf4, 5)); EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == at.get_last_error()); @@ -739,6 +735,21 @@ TEST_F(TestATHandler, test_ATHandler_read_string) // TO read from EXPECT_TRUE(6 == at.read_string(buf9, 6 + 1/*for NULL*/)); + at.clear_error(); + char table11[] = "\"1016\",\"39AB\",9\r\n\0"; + mbed_poll_stub::int_value = 0; + at.flush(); + filehandle_stub_table = table11; + filehandle_stub_table_pos = 0; + mbed_poll_stub::revents_value = POLLIN; + mbed_poll_stub::int_value = 1; + at.resp_start(); + EXPECT_TRUE(4 == at.read_string(buf4, 4 + 1/*for NULL*/)); + EXPECT_TRUE(!strncmp(buf4, "1016", 4)); + EXPECT_TRUE(4 == at.read_string(buf4, 4 + 1/*for NULL*/)); + EXPECT_TRUE(!strncmp(buf4, "39AB", 4)); + EXPECT_TRUE(9 == at.read_int()); + // *** CRLF part of the string *** at.clear_error(); char table10[] = "\"s\"\r\nOK\r\n\0"; diff --git a/features/cellular/framework/AT/ATHandler.cpp b/features/cellular/framework/AT/ATHandler.cpp index e3c6cdd39d..34db1ee665 100644 --- a/features/cellular/framework/AT/ATHandler.cpp +++ b/features/cellular/framework/AT/ATHandler.cpp @@ -460,14 +460,9 @@ ssize_t ATHandler::read_string(char *buf, size_t size, bool read_even_stop_tag) return -1; } - consume_char('\"'); - - if (_last_err) { - return -1; - } - - size_t len = 0; + int len = 0; size_t match_pos = 0; + bool delimiter_found = false; for (; len < (size - 1 + match_pos); len++) { int c = get_char(); @@ -476,6 +471,7 @@ ssize_t ATHandler::read_string(char *buf, size_t size, bool read_even_stop_tag) return -1; } else if (c == _delimiter) { buf[len] = '\0'; + delimiter_found = true; break; } else if (c == '\"') { match_pos = 0; @@ -501,6 +497,26 @@ ssize_t ATHandler::read_string(char *buf, size_t size, bool read_even_stop_tag) buf[len] = '\0'; } + // Consume to delimiter or stop_tag + if (!delimiter_found && !_stop_tag->found) { + match_pos = 0; + while(1) { + int c = get_char(); + if (c == -1) { + set_error(NSAPI_ERROR_DEVICE_ERROR); + break; + } else if (c == _delimiter) { + break; + } else if (_stop_tag->len && c == _stop_tag->tag[match_pos]) { + match_pos++; + if (match_pos == _stop_tag->len) { + _stop_tag->found = true; + break; + } + } + } + } + return len; } @@ -830,6 +846,7 @@ void ATHandler::resp_start(const char *prefix, bool stop) return; } + set_scope(NotSet); // Try get as much data as possible rewind_buffer(); (void)fill_buffer(false); From ffb9cdb4b3df426c18fc74adae0d75e695be7c83 Mon Sep 17 00:00:00 2001 From: Mirela Chirica Date: Mon, 24 Sep 2018 10:12:33 +0300 Subject: [PATCH 2/2] Cellular: Registration parameters as struct --- .../at_cellularnetworktest.cpp | 138 ++++++------ .../framework/common/util/utiltest.cpp | 17 ++ UNITTESTS/stubs/AT_CellularNetwork_stub.cpp | 10 +- .../TESTS/api/cellular_network/main.cpp | 11 +- .../easy_cellular/CellularConnectionFSM.cpp | 4 +- .../cellular/framework/API/CellularNetwork.h | 65 ++++-- .../framework/AT/AT_CellularNetwork.cpp | 213 +++++++++++------- .../framework/AT/AT_CellularNetwork.h | 30 ++- .../framework/common/CellularUtil.cpp | 20 ++ .../cellular/framework/common/CellularUtil.h | 9 + 10 files changed, 327 insertions(+), 190 deletions(-) diff --git a/UNITTESTS/features/cellular/framework/AT/at_cellularnetwork/at_cellularnetworktest.cpp b/UNITTESTS/features/cellular/framework/AT/at_cellularnetwork/at_cellularnetworktest.cpp index a498db66f8..d555d55a18 100644 --- a/UNITTESTS/features/cellular/framework/AT/at_cellularnetwork/at_cellularnetworktest.cpp +++ b/UNITTESTS/features/cellular/framework/AT/at_cellularnetwork/at_cellularnetworktest.cpp @@ -434,7 +434,7 @@ TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_set_registration) EXPECT_TRUE(NSAPI_ERROR_OK == cn.set_registration("12345")); } -TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_get_registration_status) +TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_get_registration_params) { EventQueue que; FileHandle_stub fh1; @@ -443,33 +443,86 @@ TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_get_registration_status) AT_CellularNetwork cn(at); ATHandler_stub::nsapi_error_value = NSAPI_ERROR_OK; ATHandler_stub::int_value = 3; - CellularNetwork::RegistrationStatus stat = CellularNetwork::NotRegistered; - EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_registration_status(CellularNetwork::C_EREG, stat)); - EXPECT_TRUE(stat == CellularNetwork::RegistrationDenied); - stat = CellularNetwork::NotRegistered; - EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_registration_status(CellularNetwork::C_GREG, stat)); - EXPECT_TRUE(stat == CellularNetwork::RegistrationDenied); + CellularNetwork::registration_params_t reg_params; + CellularNetwork::registration_params_t reg_params_check; + + EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_registration_params(CellularNetwork::C_EREG, reg_params)); + EXPECT_TRUE(reg_params._status == CellularNetwork::RegistrationDenied); + EXPECT_TRUE(reg_params._act == CellularNetwork::RAT_EGPRS); + EXPECT_TRUE(reg_params._cell_id == -1); + + ATHandler_stub::read_string_index = 4; + ATHandler_stub::read_string_table[3] = "00C3"; + ATHandler_stub::read_string_table[2] = "1234FFC1";//== cellid and in dec: 305463233 + ATHandler_stub::read_string_table[1] = "00100100"; + ATHandler_stub::read_string_table[0] = "01000111"; + EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_registration_params(CellularNetwork::C_EREG, reg_params)); + EXPECT_TRUE(reg_params._cell_id == 305463233); + EXPECT_TRUE(reg_params._active_time == 240); + EXPECT_TRUE(reg_params._periodic_tau == 70 * 60 *60); + ATHandler_stub::read_string_index = kRead_string_table_size; + ATHandler_stub::read_string_value = NULL; + ATHandler_stub::ssize_value = 0; + // Check get_registration_params without specifying the registration type + EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_registration_params(reg_params_check)); + EXPECT_TRUE(reg_params_check._status == CellularNetwork::RegistrationDenied); + EXPECT_TRUE(reg_params_check._act == CellularNetwork::RAT_EGPRS); + EXPECT_TRUE(reg_params_check._cell_id == 305463233); + EXPECT_TRUE(reg_params_check._active_time == 240); + EXPECT_TRUE(reg_params_check._periodic_tau == 70 * 60 *60); + + reg_params._status = CellularNetwork::NotRegistered; + reg_params._act = CellularNetwork::RAT_GSM; + reg_params._cell_id = 1; + EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_registration_params(CellularNetwork::C_GREG, reg_params)); + EXPECT_TRUE(reg_params._status == CellularNetwork::RegistrationDenied); + EXPECT_TRUE(reg_params._act == CellularNetwork::RAT_EGPRS); + EXPECT_TRUE(reg_params._cell_id == -1); my_AT_CN nw(at); - stat = CellularNetwork::NotRegistered; - EXPECT_TRUE(NSAPI_ERROR_UNSUPPORTED == nw.get_registration_status(CellularNetwork::C_GREG, stat)); - EXPECT_TRUE(stat == CellularNetwork::NotRegistered); - EXPECT_TRUE(NSAPI_ERROR_OK == nw.get_registration_status(CellularNetwork::C_EREG, stat)); - EXPECT_TRUE(stat == CellularNetwork::RegistrationDenied); + reg_params._status = CellularNetwork::NotRegistered; + reg_params._act = CellularNetwork::RAT_GSM; + EXPECT_TRUE(NSAPI_ERROR_UNSUPPORTED == nw.get_registration_params(CellularNetwork::C_GREG, reg_params)); + EXPECT_TRUE(reg_params._status == CellularNetwork::NotRegistered); + EXPECT_TRUE(reg_params._act == CellularNetwork::RAT_GSM); + + EXPECT_TRUE(NSAPI_ERROR_OK == nw.get_registration_params(CellularNetwork::C_EREG, reg_params)); + EXPECT_TRUE(reg_params._status == CellularNetwork::RegistrationDenied); + EXPECT_TRUE(reg_params._act == CellularNetwork::RAT_EGPRS); ATHandler_stub::nsapi_error_value = NSAPI_ERROR_DEVICE_ERROR; - stat = CellularNetwork::NotRegistered; - EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == cn.get_registration_status(CellularNetwork::C_EREG, stat)); - EXPECT_TRUE(stat == -1); - EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == cn.get_registration_status(CellularNetwork::C_GREG, stat)); - EXPECT_TRUE(stat == -1); + reg_params._status = CellularNetwork::NotRegistered; + reg_params._act = CellularNetwork::RAT_GSM; + reg_params._cell_id = 1; + reg_params._active_time = 2; + reg_params._periodic_tau = 3; - stat = CellularNetwork::NotRegistered; - EXPECT_TRUE(NSAPI_ERROR_UNSUPPORTED == nw.get_registration_status(CellularNetwork::C_GREG, stat)); - EXPECT_TRUE(stat == CellularNetwork::NotRegistered); - EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == nw.get_registration_status(CellularNetwork::C_EREG, stat)); - EXPECT_TRUE(stat == -1); + EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == cn.get_registration_params(CellularNetwork::C_EREG, reg_params)); + EXPECT_TRUE(reg_params._status == CellularNetwork::StatusNotAvailable); + EXPECT_TRUE(reg_params._act == CellularNetwork::RAT_UNKNOWN); + EXPECT_TRUE(reg_params._cell_id == -1 && reg_params._active_time == -1 && reg_params._periodic_tau == -1); + + EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == cn.get_registration_params(CellularNetwork::C_GREG, reg_params)); + EXPECT_TRUE(reg_params._status == CellularNetwork::StatusNotAvailable); + EXPECT_TRUE(reg_params._act == CellularNetwork::RAT_UNKNOWN); + EXPECT_TRUE(reg_params._cell_id == -1); + + reg_params._status = CellularNetwork::SearchingNetwork; + reg_params._act = CellularNetwork::RAT_GSM; + reg_params._cell_id = 1; + reg_params._active_time = 2; + reg_params._periodic_tau = 3; + + EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == nw.get_registration_params(CellularNetwork::C_EREG, reg_params)); + EXPECT_TRUE(reg_params._status == CellularNetwork::StatusNotAvailable); + EXPECT_TRUE(reg_params._act == CellularNetwork::RAT_UNKNOWN); + EXPECT_TRUE(reg_params._cell_id == -1 && reg_params._active_time == -1 && reg_params._periodic_tau == -1); + // Check get_registration_params without specifying the registration type + EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_registration_params(reg_params_check)); + EXPECT_TRUE(reg_params_check._status == CellularNetwork::StatusNotAvailable); + EXPECT_TRUE(reg_params_check._act == CellularNetwork::RAT_UNKNOWN); + EXPECT_TRUE(reg_params_check._cell_id == -1 && reg_params_check._active_time == -1 && reg_params_check._periodic_tau == -1); } TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_get_network_registering_mode) @@ -762,19 +815,6 @@ TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_set_access_technology) EXPECT_TRUE(NSAPI_ERROR_OK == my_cn.set_access_technology(CellularNetwork::RAT_GSM_COMPACT)); } -TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_get_access_technology) -{ - EventQueue que; - FileHandle_stub fh1; - ATHandler at(&fh1, que, 0, ","); - - AT_CellularNetwork cn(at); - CellularNetwork::RadioAccessTechnology rat; - - EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_access_technology(rat)); - EXPECT_TRUE(CellularNetwork::RAT_UNKNOWN == rat); -} - TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_scan_plmn) { EventQueue que; @@ -989,34 +1029,6 @@ TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_get_signal_quality) EXPECT_TRUE(rs == 1 && ber == 1); } -TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_get_cell_id) -{ - EventQueue que; - FileHandle_stub fh1; - ATHandler at(&fh1, que, 0, ","); - - AT_CellularNetwork cn(at); - int id = 0; - EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_cell_id(id)); - EXPECT_TRUE(id == -1); - - ATHandler_stub::nsapi_error_value = NSAPI_ERROR_DEVICE_ERROR; - EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_cell_id(id)); - EXPECT_TRUE(id == -1); - - ATHandler_stub::read_string_index = 2; - ATHandler_stub::read_string_table[1] = (char *)"00C3"; - ATHandler_stub::read_string_table[0] = (char *)"1234FFC1"; //== cellid and in dec: 305463233 - ATHandler_stub::int_value = 1; - // Get registration status to modify cell_id - CellularNetwork::RegistrationType type; - CellularNetwork::RegistrationStatus status; - ATHandler_stub::nsapi_error_value = NSAPI_ERROR_OK; - EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_registration_status(CellularNetwork::C_EREG, status)); - EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_cell_id(id)); - EXPECT_TRUE(id == 305463233); -} - TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_get_3gpp_error) { EventQueue que; diff --git a/UNITTESTS/features/cellular/framework/common/util/utiltest.cpp b/UNITTESTS/features/cellular/framework/common/util/utiltest.cpp index 4c00da93c2..b4729d56bb 100644 --- a/UNITTESTS/features/cellular/framework/common/util/utiltest.cpp +++ b/UNITTESTS/features/cellular/framework/common/util/utiltest.cpp @@ -35,6 +35,23 @@ protected: }; // *INDENT-ON* +TEST_F(Testutil, test_util_binary_str_to_uint) +{ + char binary_str[]="011001011101101000"; + uint32_t value = binary_str_to_uint(binary_str, strlen(binary_str) + 1); + EXPECT_TRUE(value == 104296); + value = binary_str_to_uint(binary_str, strlen(binary_str)); + EXPECT_TRUE(value == 104296); + value = binary_str_to_uint(binary_str, strlen(binary_str) - 1); + EXPECT_TRUE(value == 52148); + value = binary_str_to_uint(binary_str, strlen(binary_str) - 3); + EXPECT_TRUE(value == 13037); + value = binary_str_to_uint(binary_str + 5, strlen(binary_str) - 5); + EXPECT_TRUE(value == 5992); + EXPECT_TRUE(0 == binary_str_to_uint(NULL, 5)); + EXPECT_TRUE(0 == binary_str_to_uint(binary_str, 0)); +} + TEST_F(Testutil, test_util_uint_to_binary_string) { char str[33]; diff --git a/UNITTESTS/stubs/AT_CellularNetwork_stub.cpp b/UNITTESTS/stubs/AT_CellularNetwork_stub.cpp index b28c8ebb9e..c976abdf91 100644 --- a/UNITTESTS/stubs/AT_CellularNetwork_stub.cpp +++ b/UNITTESTS/stubs/AT_CellularNetwork_stub.cpp @@ -111,12 +111,12 @@ nsapi_error_t AT_CellularNetwork::set_registration(const char *plmn) return NSAPI_ERROR_OK; } -nsapi_error_t AT_CellularNetwork::get_registration_status(RegistrationType type, RegistrationStatus &status) +nsapi_error_t AT_CellularNetwork::get_registration_params(RegistrationType type, registration_params_t ®_params) { return NSAPI_ERROR_OK; } -nsapi_error_t AT_CellularNetwork::get_cell_id(int &cell_id) +nsapi_error_t AT_CellularNetwork::get_registration_params(registration_params_t ®_params) { return NSAPI_ERROR_OK; } @@ -186,12 +186,6 @@ nsapi_error_t AT_CellularNetwork::set_access_technology(RadioAccessTechnology op return NSAPI_ERROR_OK; } -nsapi_error_t AT_CellularNetwork::get_access_technology(RadioAccessTechnology &rat) -{ - rat = RAT_CATM1; - return NSAPI_ERROR_OK; -} - nsapi_error_t AT_CellularNetwork::scan_plmn(operList_t &operators, int &opsCount) { return NSAPI_ERROR_OK; diff --git a/features/cellular/TESTS/api/cellular_network/main.cpp b/features/cellular/TESTS/api/cellular_network/main.cpp index 75b2e0c3f0..80b38c3f33 100644 --- a/features/cellular/TESTS/api/cellular_network/main.cpp +++ b/features/cellular/TESTS/api/cellular_network/main.cpp @@ -102,9 +102,11 @@ static bool get_network_registration(CellularNetwork::RegistrationType type, CellularNetwork::RegistrationStatus &status, bool &is_registered) { is_registered = false; - nsapi_error_t err = nw->get_registration_status(type, status); + CellularNetwork::registration_params_t reg_params; + nsapi_error_t err = nw->get_registration_params(type, reg_params); TEST_ASSERT(err == NSAPI_ERROR_OK || err == NSAPI_ERROR_UNSUPPORTED); + status = reg_params._status; switch (status) { case CellularNetwork::RegisteredRoaming: case CellularNetwork::RegisteredHomeNetwork: @@ -312,9 +314,10 @@ static void test_other() TEST_ASSERT(ber >= 0); } - int cell_id = -5; - TEST_ASSERT(nw->get_cell_id(cell_id) == NSAPI_ERROR_OK); - TEST_ASSERT(cell_id != -5); + CellularNetwork::registration_params_t reg_params; + reg_params._cell_id = -5; + TEST_ASSERT(nw->get_registration_params(reg_params) == NSAPI_ERROR_OK); + TEST_ASSERT(reg_params._cell_id != -5); int format = -1; CellularNetwork::operator_t operator_params; diff --git a/features/cellular/easy_cellular/CellularConnectionFSM.cpp b/features/cellular/easy_cellular/CellularConnectionFSM.cpp index e4c1415edb..39c76736ab 100644 --- a/features/cellular/easy_cellular/CellularConnectionFSM.cpp +++ b/features/cellular/easy_cellular/CellularConnectionFSM.cpp @@ -223,13 +223,15 @@ bool CellularConnectionFSM::get_network_registration(CellularNetwork::Registrati { is_registered = false; bool is_roaming = false; - nsapi_error_t err = _network->get_registration_status(type, status); + CellularNetwork::registration_params_t reg_params; + nsapi_error_t err = _network->get_registration_params(type, reg_params); if (err != NSAPI_ERROR_OK) { if (err != NSAPI_ERROR_UNSUPPORTED) { tr_warn("Get network registration failed (type %d)!", type); } return false; } + status = reg_params._status; switch (status) { case CellularNetwork::RegisteredRoaming: is_roaming = true; diff --git a/features/cellular/framework/API/CellularNetwork.h b/features/cellular/framework/API/CellularNetwork.h index 609ccd844a..2aa661fcf8 100644 --- a/features/cellular/framework/API/CellularNetwork.h +++ b/features/cellular/framework/API/CellularNetwork.h @@ -66,6 +66,7 @@ public: /* Network registration status */ enum RegistrationStatus { + StatusNotAvailable = -1, NotRegistered = 0, RegisteredHomeNetwork, SearchingNetwork, @@ -225,6 +226,27 @@ public: NWModeManualAutomatic // if manual fails, fallback to automatic }; + /* Network registration information */ + struct registration_params_t { + RegistrationType _type; + RegistrationStatus _status; + RadioAccessTechnology _act; + int _cell_id; + int _lac; + int _active_time; + int _periodic_tau; + + registration_params_t() + { + _type = C_MAX; + _status = StatusNotAvailable; + _act = RAT_UNKNOWN; + _cell_id = -1; + _lac = -1; + _active_time = -1; + _periodic_tau = -1; + } + }; /** Does all the needed initializations that can fail * @@ -263,15 +285,6 @@ public: */ virtual nsapi_error_t set_registration_urc(RegistrationType type, bool on) = 0; - /** Gets the network registration status. - * - * @param type see RegistrationType values - * @param status see RegistrationStatus values - * @return NSAPI_ERROR_OK on success - * NSAPI_ERROR_UNSUPPORTED if the modem does not support RegistrationType - * NSAPI_ERROR_DEVICE_ERROR on failure - */ - virtual nsapi_error_t get_registration_status(RegistrationType type, RegistrationStatus &status) = 0; /** Set the cellular network APN and credentials * @@ -352,13 +365,6 @@ public: */ virtual nsapi_error_t set_access_technology(RadioAccessTechnology rat) = 0; - /** Get current radio access technology. - * - * @param rat Radio access technology - * @return NSAPI_ERROR_OK - */ - virtual nsapi_error_t get_access_technology(RadioAccessTechnology &rat) = 0; - /** Scans for operators module can reach. * * @param operators Container of reachable operators and their access technologies @@ -475,13 +481,6 @@ public: */ virtual nsapi_error_t get_signal_quality(int &rssi, int &ber) = 0; - /** Get cell id. - * - * @param cell_id cell ID - * @return NSAPI_ERROR_OK - */ - virtual nsapi_error_t get_cell_id(int &cell_id) = 0; - /** Get the last 3GPP error code * @return see 3GPP TS 27.007 error codes */ @@ -528,6 +527,26 @@ public: * NSAPI_ERROR_DEVICE_ERROR on other failures */ virtual nsapi_error_t get_operator_names(operator_names_list &op_names) = 0; + + /** Gets current network registration parameters: + * type, status, access technology, cell_id, lac, active_time, periodic_tau. + * + * @param reg_params see registration_params_t + * @return NSAPI_ERROR_OK on success + * NSAPI_ERROR_DEVICE_ERROR on failure + */ + virtual nsapi_error_t get_registration_params(registration_params_t ®_params) = 0; + + /** Gets the network registration parameters based on required registration type: + * status, access technology, cell_id, lac, active_time, periodic_tau. + * + * @param type see RegistrationType values + * @param reg_params see registration_params_t + * @return NSAPI_ERROR_OK on success + * NSAPI_ERROR_UNSUPPORTED if the modem does not support RegistrationType + * NSAPI_ERROR_DEVICE_ERROR on failure + */ + virtual nsapi_error_t get_registration_params(RegistrationType type, registration_params_t ®_params) = 0; }; } // namespace mbed diff --git a/features/cellular/framework/AT/AT_CellularNetwork.cpp b/features/cellular/framework/AT/AT_CellularNetwork.cpp index 4c6a960c56..b499721773 100644 --- a/features/cellular/framework/AT/AT_CellularNetwork.cpp +++ b/features/cellular/framework/AT/AT_CellularNetwork.cpp @@ -41,8 +41,8 @@ static const at_reg_t at_reg[] = { 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), _cell_id(-1), _connect_status(NSAPI_STATUS_DISCONNECTED), _new_context_set(false), - _is_context_active(false), _reg_status(NotRegistered), _current_act(RAT_UNKNOWN) + _authentication_type(CHAP), _connect_status(NSAPI_STATUS_DISCONNECTED), _new_context_set(false), + _is_context_active(false) { } @@ -138,13 +138,11 @@ void AT_CellularNetwork::urc_cgev() 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(type, reg_status, lac, cell_id, act); + registration_params_t reg_params; + read_reg_params(reg_params); #if MBED_CONF_MBED_TRACE_ENABLE - switch (reg_status) { + switch (reg_params._status) { case NotRegistered: tr_warn("not registered"); break; @@ -160,18 +158,19 @@ void AT_CellularNetwork::read_reg_params_and_compare(RegistrationType type) #endif 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); + tr_debug("type: %d, status: %d, lac: %d, cellID: %d, act: %d", type, reg_params._status, reg_params._lac, reg_params._cell_id, reg_params._act); + _reg_params._type = type; + if (reg_params._act != _reg_params._act) { + _reg_params._act = reg_params._act; + _connection_status_cb((nsapi_event_t)CellularRadioAccessTechnologyChanged, _reg_params._act); } - if (reg_status != _reg_status) { - _reg_status = reg_status; - _connection_status_cb((nsapi_event_t)CellularRegistrationStatusChanged, _reg_status); + if (reg_params._status != _reg_params._status) { + _reg_params._status = reg_params._status; + _connection_status_cb((nsapi_event_t)CellularRegistrationStatusChanged, _reg_params._status); } - if (cell_id != -1 && cell_id != _cell_id) { - _cell_id = cell_id; - _connection_status_cb((nsapi_event_t)CellularCellIDChanged, _cell_id); + if (reg_params._cell_id != -1 && reg_params._cell_id != _reg_params._cell_id) { + _reg_params._cell_id = reg_params._cell_id; + _connection_status_cb((nsapi_event_t)CellularCellIDChanged, _reg_params._cell_id); } } } @@ -455,7 +454,7 @@ nsapi_error_t AT_CellularNetwork::disconnect() // 3GPP TS 27.007: // For EPS, if an attempt is made to disconnect the last PDN connection, then the MT responds with ERROR - if (_is_context_active && (_current_act < RAT_E_UTRAN || active_contexts_count > 1)) { + if (_is_context_active && (_reg_params._act < RAT_E_UTRAN || active_contexts_count > 1)) { _at.cmd_start("AT+CGACT=0,"); _at.write_int(_cid); _at.cmd_stop(); @@ -785,76 +784,49 @@ nsapi_error_t AT_CellularNetwork::set_registration(const char *plmn) return _at.unlock_return_error(); } -void AT_CellularNetwork::read_reg_params(RegistrationType type, RegistrationStatus ®_status, int &lac, int &cell_id, int &act) +void AT_CellularNetwork::read_reg_params(registration_params_t ®_params) { - const int LAC_LENGTH = 5, CELL_ID_LENGTH = 9; - char lac_string[LAC_LENGTH] = {0}, cell_id_string[CELL_ID_LENGTH] = {0}; - bool lac_read = false, cell_id_read = false; + const int MAX_STRING_LENGTH = 9; + char string_param[MAX_STRING_LENGTH] = {0}; - reg_status = (RegistrationStatus)_at.read_int(); + int int_param = _at.read_int(); + reg_params._status = (RegistrationStatus)int_param; - int len = _at.read_string(lac_string, LAC_LENGTH); - if (memcmp(lac_string, "ffff", LAC_LENGTH - 1) && len >= 0) { - lac_read = true; + int len = _at.read_string(string_param, TWO_BYTES_HEX + 1); + if (len > 0) { + reg_params._lac = hex_str_to_int(string_param, TWO_BYTES_HEX); + tr_debug("lac %s %d", string_param, reg_params._lac); + } else { + reg_params._lac = -1; } - len = _at.read_string(cell_id_string, CELL_ID_LENGTH); - if (memcmp(cell_id_string, "ffffffff", CELL_ID_LENGTH - 1) && len >= 0) { - cell_id_read = true; + len = _at.read_string(string_param, FOUR_BYTES_HEX + 1); + if (len > 0) { + reg_params._cell_id = hex_str_to_int(string_param, FOUR_BYTES_HEX); + tr_debug("cell_id %s %d", string_param, reg_params._cell_id); + } else { + reg_params._cell_id = -1; } - act = _at.read_int(); + int_param = _at.read_int(); + reg_params._act = (int_param == -1) ? RAT_UNKNOWN : (RadioAccessTechnology)int_param; - if (lac_read) { - lac = hex_str_to_int(lac_string, LAC_LENGTH); - tr_debug("lac %s %d", lac_string, lac); + // Skip [],[] + _at.skip_param(2); + + len = _at.read_string(string_param, ONE_BYTE_BINARY + 1); + reg_params._active_time = calculate_active_time(string_param, len); + if (reg_params._active_time != -1) { + tr_debug("active_time %s %d", string_param, reg_params._active_time); } - if (cell_id_read) { - cell_id = hex_str_to_int(cell_id_string, CELL_ID_LENGTH); - tr_debug("cell_id %s %d", cell_id_string, cell_id); + len = _at.read_string(string_param, ONE_BYTE_BINARY + 1); + reg_params._periodic_tau = calculate_periodic_tau(string_param, len); + if (reg_params._periodic_tau == -1) { + tr_debug("periodic_tau %s %d", string_param, reg_params._periodic_tau); } } -nsapi_error_t AT_CellularNetwork::get_registration_status(RegistrationType type, RegistrationStatus &status) -{ - int i = (int)type; - MBED_ASSERT(i >= 0 && i < C_MAX); - - if (has_registration(at_reg[i].type) == RegistrationModeDisable) { - return NSAPI_ERROR_UNSUPPORTED; - } - - _at.lock(); - - const char *rsp[] = { "+CEREG:", "+CGREG:", "+CREG:"}; - _at.cmd_start(at_reg[i].cmd); - _at.write_string("?", false); - _at.cmd_stop(); - _at.resp_start(rsp[i]); - - (void)_at.read_int(); // ignore urc mode subparam - 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; - } - if (act != -1) { - _current_act = (RadioAccessTechnology)act; - } - - return _at.unlock_return_error(); -} - -nsapi_error_t AT_CellularNetwork::get_cell_id(int &cell_id) -{ - cell_id = _cell_id; - return NSAPI_ERROR_OK; -} - AT_CellularNetwork::RegistrationMode AT_CellularNetwork::has_registration(RegistrationType reg_type) { (void)reg_type; @@ -988,12 +960,6 @@ nsapi_error_t AT_CellularNetwork::set_access_technology_impl(RadioAccessTechnolo return NSAPI_ERROR_UNSUPPORTED; } -nsapi_error_t AT_CellularNetwork::get_access_technology(RadioAccessTechnology &rat) -{ - rat = _current_act; - return NSAPI_ERROR_OK; -} - nsapi_error_t AT_CellularNetwork::set_access_technology(RadioAccessTechnology opAct) { if (opAct == RAT_UNKNOWN) { @@ -1329,3 +1295,88 @@ nsapi_error_t AT_CellularNetwork::get_operator_names(operator_names_list &op_nam _at.resp_stop(); return _at.unlock_return_error(); } + +nsapi_error_t AT_CellularNetwork::get_registration_params(registration_params_t ®_params) +{ + reg_params = _reg_params; + return NSAPI_ERROR_OK; +} + +nsapi_error_t AT_CellularNetwork::get_registration_params(RegistrationType type, registration_params_t ®_params) +{ + int i = (int)type; + MBED_ASSERT(i >= 0 && i < C_MAX); + + if (!has_registration(at_reg[i].type)) { + return NSAPI_ERROR_UNSUPPORTED; + } + + _at.lock(); + + const char *rsp[] = { "+CEREG:", "+CGREG:", "+CREG:"}; + _at.cmd_start(at_reg[i].cmd); + _at.write_string("?", false); + _at.cmd_stop(); + _at.resp_start(rsp[i]); + + (void)_at.read_int(); // ignore urc mode subparam + _reg_params._type = type; + read_reg_params(reg_params); + _at.resp_stop(); + + _reg_params = reg_params; + + return _at.unlock_return_error(); +} + +int AT_CellularNetwork::calculate_active_time(const char *active_time_string, int active_time_length) +{ + if (active_time_length != ONE_BYTE_BINARY) { + return -1; + } + + uint32_t ie_unit = binary_str_to_uint(active_time_string, TIMER_UNIT_LENGTH); + uint32_t ie_value = binary_str_to_uint(active_time_string + TIMER_UNIT_LENGTH, active_time_length - TIMER_UNIT_LENGTH); + + switch (ie_unit) { + case 0: // multiples of 2 seconds + return 2 * ie_value; + case 1: // multiples of 1 minute + return 60 * ie_value; + case 2: // multiples of decihours + return 6 * 60 * ie_value; + case 7: // timer is deactivated + return 0; + default: // other values shall be interpreted as multiples of 1 minute + return 60 * ie_value; + } +} + +int AT_CellularNetwork::calculate_periodic_tau(const char *periodic_tau_string, int periodic_tau_length) +{ + if (periodic_tau_length != ONE_BYTE_BINARY) { + return -1; + } + + uint32_t ie_unit = binary_str_to_uint(periodic_tau_string, TIMER_UNIT_LENGTH); + uint32_t ie_value = binary_str_to_uint(periodic_tau_string + TIMER_UNIT_LENGTH, periodic_tau_length - TIMER_UNIT_LENGTH); + + switch (ie_unit) { + case 0: // multiples of 10 minutes + return 60 * 10 * ie_value; + case 1: // multiples of 1 hour + return 60 * 60 * ie_value; + case 2: // multiples of 10 hours + return 10 * 60 * 60 * ie_value; + case 3: // multiples of 2 seconds + return 2 * ie_value; + case 4: // multiples of 30 seconds + return 30 * ie_value; + case 5: // multiples of 1 minute + return 60 * ie_value; + case 6: // multiples of 320 hours + return 320 * 60 * 60 * ie_value; + default: // timer is deactivated + return 0; + } +} diff --git a/features/cellular/framework/AT/AT_CellularNetwork.h b/features/cellular/framework/AT/AT_CellularNetwork.h index 80b5665b83..f33e162d66 100644 --- a/features/cellular/framework/AT/AT_CellularNetwork.h +++ b/features/cellular/framework/AT/AT_CellularNetwork.h @@ -25,6 +25,10 @@ namespace mbed { #define AT_NETWORK_TRIALS 5 +#define TIMER_UNIT_LENGTH 3 +#define TWO_BYTES_HEX 4 +#define FOUR_BYTES_HEX 8 +#define ONE_BYTE_BINARY 8 /** * Class AT_CellularNetwork @@ -67,8 +71,6 @@ public: // CellularNetwork virtual nsapi_error_t get_network_registering_mode(NWRegisteringMode &mode); - virtual nsapi_error_t get_registration_status(RegistrationType type, RegistrationStatus &status); - virtual nsapi_error_t set_attach(int timeout = 10 * 1000); virtual nsapi_error_t get_attach(AttachStatus &status); @@ -89,7 +91,6 @@ public: // CellularNetwork virtual const char *get_ip_address(); virtual nsapi_error_t set_access_technology(RadioAccessTechnology rat); - virtual nsapi_error_t get_access_technology(RadioAccessTechnology &rat); virtual nsapi_error_t scan_plmn(operList_t &operators, int &ops_count); @@ -109,8 +110,6 @@ public: // CellularNetwork virtual nsapi_error_t get_signal_quality(int &rssi, int &ber); - virtual nsapi_error_t get_cell_id(int &cell_id); - virtual int get_3gpp_error(); virtual nsapi_error_t get_operator_params(int &format, operator_t &operator_params); @@ -118,6 +117,10 @@ public: // CellularNetwork virtual nsapi_error_t set_registration_urc(RegistrationType type, bool on); virtual nsapi_error_t get_operator_names(operator_names_list &op_names); + + virtual nsapi_error_t get_registration_params(registration_params_t ®_params); + + virtual nsapi_error_t get_registration_params(RegistrationType type, registration_params_t ®_params); protected: /** Check if modem supports the given stack type. @@ -171,10 +174,17 @@ private: nsapi_error_t delete_current_context(); - void read_reg_params_and_compare(RegistrationType type); - void read_reg_params(RegistrationType type, RegistrationStatus ®_status, int &lac, int &cell_id, int &act); // calls network callback only if status was changed, updates local connection status void call_network_cb(nsapi_connection_status_t status); + + void read_reg_params_and_compare(RegistrationType type); + void read_reg_params(registration_params_t ®_params); + + // Returns active time(Table 10.5.163/3GPP TS 24.008: GPRS Timer 2 information element) in seconds + int calculate_active_time(const char *active_time_string, int active_time_length); + // Returns periodic tau(Table 10.5.163a/3GPP TS 24.008: GPRS Timer 3 information element) in seconds + int calculate_periodic_tau(const char *periodic_tau_string, int periodic_tau_length); + #if NSAPI_PPP_AVAILABLE void ppp_status_cb(nsapi_event_t, intptr_t); #endif @@ -190,12 +200,12 @@ protected: Callback _connection_status_cb; RadioAccessTechnology _op_act; AuthenticationType _authentication_type; - int _cell_id; nsapi_connection_status_t _connect_status; bool _new_context_set; bool _is_context_active; - RegistrationStatus _reg_status; - RadioAccessTechnology _current_act; + + registration_params_t _reg_params; + mbed::Callback _urc_funcs[C_MAX]; }; diff --git a/features/cellular/framework/common/CellularUtil.cpp b/features/cellular/framework/common/CellularUtil.cpp index c68dec2925..b1cdc2a0c8 100644 --- a/features/cellular/framework/common/CellularUtil.cpp +++ b/features/cellular/framework/common/CellularUtil.cpp @@ -300,6 +300,26 @@ void uint_to_binary_str(uint32_t num, char *str, int str_size, int bit_cnt) } } +uint32_t binary_str_to_uint(const char *binary_string, int binary_string_length) +{ + if (!binary_string || !binary_string_length) { + return 0; + } + + int integer_output = 0, base_exp = 1; + + for (int i = binary_string_length - 1; i >= 0; i--) { + if (binary_string[i] == '1') { + integer_output += base_exp; + } + if (binary_string[i] != '\0') { + base_exp <<= 1; + } + } + + return integer_output; +} + int char_str_to_hex_str(const char *str, uint16_t len, char *buf, bool omit_leading_zero) { if (!str || !buf) { diff --git a/features/cellular/framework/common/CellularUtil.h b/features/cellular/framework/common/CellularUtil.h index 46f66162e7..b9b0db95da 100644 --- a/features/cellular/framework/common/CellularUtil.h +++ b/features/cellular/framework/common/CellularUtil.h @@ -105,6 +105,15 @@ int hex_str_to_char_str(const char *str, uint16_t len, char *buf); */ void uint_to_binary_str(uint32_t num, char *str, int str_size, int bit_cnt); +/** Converts the given binary string to uint. + * For example binary_str_to_uint("0000001001", 10) would return 9 + * + * @param binary_string binary string from where chars are converted to uint + * @param binary_string_length length of the param binary_string + * @return uint represented by the binary string + */ +uint32_t binary_str_to_uint(const char *binary_string, int binary_string_length); + /** Get dynamic port for socket * * @return next port number above 49152