diff --git a/UNITTESTS/features/cellular/framework/AT/at_cellularbase/unittest.cmake b/UNITTESTS/features/cellular/framework/AT/at_cellularbase/unittest.cmake index 32d9d47208..eab77c34eb 100644 --- a/UNITTESTS/features/cellular/framework/AT/at_cellularbase/unittest.cmake +++ b/UNITTESTS/features/cellular/framework/AT/at_cellularbase/unittest.cmake @@ -16,7 +16,6 @@ set(unittest-includes ${unittest-includes} # Source files set(unittest-sources ../features/cellular/framework/AT/AT_CellularBase.cpp - ../features/cellular/framework/AT/ATHandler_factory.cpp ) # Test files diff --git a/UNITTESTS/features/cellular/framework/AT/at_cellularcontext/at_cellularcontexttest.cpp b/UNITTESTS/features/cellular/framework/AT/at_cellularcontext/at_cellularcontexttest.cpp index e977ee6dd6..a8acae727c 100644 --- a/UNITTESTS/features/cellular/framework/AT/at_cellularcontext/at_cellularcontexttest.cpp +++ b/UNITTESTS/features/cellular/framework/AT/at_cellularcontext/at_cellularcontexttest.cpp @@ -28,6 +28,8 @@ #include "CellularDevice_stub.h" #include "equeue_stub.h" #include "AT_CellularBase_stub.h" +#include "CellularUtil_stub.h" +#include "PinNames.h" using namespace mbed; using namespace events; @@ -62,6 +64,9 @@ protected: ATHandler_stub::read_string_table[kRead_string_table_size]; ATHandler_stub::resp_stop_success_count = kResp_stop_count_default; CellularDevice_stub::connect_counter = 2; + + CellularUtil_stub::char_table[0] = (char *)"\0"; + CellularUtil_stub::table_idx = 0; } void TearDown() @@ -131,6 +136,16 @@ public: AT_CellularContext::cellular_callback(ev, ptr); } + void activ_non_ip_context() + { + activate_non_ip_context(); + } + + void deactiv_non_ip_context() + { + deactivate_non_ip_context(); + } + my_stack _st; }; @@ -150,6 +165,19 @@ public: my_stack _st; }; +class def_AT_CTX : public AT_CellularContext { +public: + def_AT_CTX(ATHandler &at, CellularDevice *device, const char *apn = MBED_CONF_NSAPI_DEFAULT_CELLULAR_APN) : + AT_CellularContext(at, device, apn) {} + virtual ~def_AT_CTX() {} + + uint32_t do_op() + { + return AT_CellularContext::get_timeout_for_operation(mbed::CellularContext::ContextOperation(_op)); + } + int _op; +}; + static int network_cb_count; static void network_cb(nsapi_event_t ev, intptr_t intptr) { @@ -169,6 +197,9 @@ TEST_F(TestAT_CellularContext, Create) ctx = new AT_CellularContext(at, &dev); EXPECT_TRUE(ctx != NULL); + + ctx->get_device(); + EXPECT_EQ(NSAPI_STATUS_DISCONNECTED, ctx->get_connection_status()); delete ctx; } @@ -325,6 +356,20 @@ TEST_F(TestAT_CellularContext, get_pdpcontext_params) ATHandler_stub::read_string_table[1] = (char *)"25.66.77.88"; ATHandler_stub::read_string_table[0] = (char *)"004.003.002.001"; + CellularUtil_stub::table_idx = 12; + CellularUtil_stub::char_table[11] = (char *)"102:304:506:708:90A:B70:D0E:F10\0"; + CellularUtil_stub::char_table[10] = (char *)"102:32C:3706:708:90A:B0C:D0E:F10\0"; + CellularUtil_stub::char_table[9] = (char *)"1721:2C01:203:377B:E122:B01:000:7BEA\0"; + CellularUtil_stub::char_table[8] = (char *)"1.2.3.4\0"; + CellularUtil_stub::char_table[7] = (char *)"1.2.3.4\0"; + CellularUtil_stub::char_table[6] = (char *)"1.2.3.4\0"; + CellularUtil_stub::char_table[5] = (char *)"0.255.0.255\0"; + CellularUtil_stub::char_table[4] = (char *)"1.2.3.4\0"; + CellularUtil_stub::char_table[3] = (char *)"25.66.77.88\0"; + CellularUtil_stub::char_table[2] = (char *)"1.2.3.4\0"; + CellularUtil_stub::char_table[1] = (char *)"004.003.002.001\0"; + CellularUtil_stub::char_table[0] = (char *)"1.2.3.4\0"; + EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_pdpcontext_params(list)); CellularContext::pdpcontext_params_t *params = list.get_head(); EXPECT_TRUE(params != NULL); @@ -457,6 +502,11 @@ TEST_F(TestAT_CellularContext, set_file_handle) AT_CellularDevice dev(&fh1); AT_CellularContext ctx(at, &dev); ctx.set_file_handle(&fh1); + + UARTSerial ss(NC, NC); + + ctx.set_file_handle(&ss, PTC0, true); + ctx.enable_hup(true); } TEST_F(TestAT_CellularContext, connect_disconnect_sync) @@ -481,10 +531,44 @@ TEST_F(TestAT_CellularContext, connect_disconnect_sync) data.error = NSAPI_ERROR_OK; ctx1.cellular_callback((nsapi_event_t)CellularDeviceReady, (intptr_t)&data); + ATHandler_stub::resp_info_true_counter = 1; + ATHandler_stub::read_string_table[0] = (char *)"APN"; + ATHandler_stub::read_string_table[1] = (char *)"IP"; + ATHandler_stub::read_string_index = 2; ASSERT_EQ(ctx1.connect(), NSAPI_ERROR_OK); ASSERT_EQ(network_cb_count, 5); + ASSERT_EQ(ctx1.disconnect(), NSAPI_ERROR_OK); + ATHandler_stub::resp_info_true_counter = 1; + ATHandler_stub::read_string_table[1] = (char *)"Non-IP"; + ATHandler_stub::read_string_index = 2; + ASSERT_EQ(ctx1.connect(), NSAPI_ERROR_OK); + + ASSERT_EQ(ctx1.disconnect(), NSAPI_ERROR_OK); + ATHandler_stub::resp_info_true_counter = 1; + ATHandler_stub::read_string_table[1] = (char *)"IPV6"; + ATHandler_stub::read_string_index = 2; + ASSERT_EQ(ctx1.connect(), NSAPI_ERROR_OK); + + AT_CellularBase_stub::supported_bool = true; + ASSERT_EQ(ctx1.disconnect(), NSAPI_ERROR_OK); + ATHandler_stub::resp_info_true_counter = 1; + ATHandler_stub::read_string_table[1] = (char *)"IPV4V6"; + ATHandler_stub::read_string_index = 2; + ASSERT_EQ(ctx1.connect(), NSAPI_ERROR_OK); + AT_CellularBase_stub::supported_bool = false; + + ASSERT_EQ(ctx1.disconnect(), NSAPI_ERROR_OK); + ATHandler_stub::resp_info_true_counter = 1; + ATHandler_stub::read_string_table[0] = (char *)"APN2"; + ATHandler_stub::read_string_table[1] = (char *)"IPV4V6"; + ATHandler_stub::read_string_index = 2; + ATHandler_stub::int_value = 10; + ctx1.set_credentials("APN"); + ASSERT_EQ(ctx1.connect(), NSAPI_ERROR_OK); + ATHandler_stub::int_value = -1; + ASSERT_EQ(ctx1.connect(), NSAPI_ERROR_IS_CONNECTED); EXPECT_TRUE(ctx1.is_connected() == true); @@ -519,6 +603,26 @@ TEST_F(TestAT_CellularContext, connect_disconnect_sync) // More connect test after we are re-writted getting of PDP context... } +TEST_F(TestAT_CellularContext, de_and_activate_non_ip_context) +{ + EventQueue que; + FileHandle_stub fh1; + ATHandler at(&fh1, que, 0, ","); + AT_CellularDevice dev(&fh1); + my_AT_CTX ctx(at, &dev); + ctx.attach(&network_cb); + Semaphore_stub::acquire_return_value = true; + + // call callback so that network is opened which is needed in disconnect + cell_callback_data_t data; + data.error = NSAPI_ERROR_OK; + ctx.cellular_callback((nsapi_event_t)CellularDeviceReady, (intptr_t)&data); + + ctx.activ_non_ip_context(); + + ctx.deactiv_non_ip_context(); +} + TEST_F(TestAT_CellularContext, set_device_ready_sync) { EventQueue que; @@ -625,3 +729,22 @@ TEST_F(TestAT_CellularContext, connect_disconnect_async) // More connect test after we are re-writted getting of PDP context... } + +TEST_F(TestAT_CellularContext, get_timeout_for_operation) +{ + EventQueue que; + FileHandle_stub fh1; + ATHandler at(&fh1, que, 0, ","); + + AT_CellularDevice dev(&fh1); + def_AT_CTX ctx1(at, &dev); + ctx1._op = 1; + EXPECT_EQ(300 * 1000, ctx1.do_op()); + + ctx1._op = 0; + EXPECT_EQ(300 * 1000, ctx1.do_op()); + + ctx1._op = -1; + EXPECT_EQ(1800 * 1000, ctx1.do_op()); + +} diff --git a/UNITTESTS/features/cellular/framework/AT/at_cellularcontext/unittest.cmake b/UNITTESTS/features/cellular/framework/AT/at_cellularcontext/unittest.cmake index 8a8910cfb7..761d1ee357 100644 --- a/UNITTESTS/features/cellular/framework/AT/at_cellularcontext/unittest.cmake +++ b/UNITTESTS/features/cellular/framework/AT/at_cellularcontext/unittest.cmake @@ -15,8 +15,6 @@ set(unittest-includes ${unittest-includes} # Source files set(unittest-sources ../features/cellular/framework/AT/AT_CellularContext.cpp - ../features/cellular/framework/AT/ATHandler_factory.cpp - ../features/cellular/framework/common/CellularUtil.cpp ) # Test files @@ -42,4 +40,5 @@ set(unittest-test-sources stubs/UARTSerial_stub.cpp stubs/SerialBase_stub.cpp stubs/CellularContext_stub.cpp + stubs/CellularUtil_stub.cpp ) diff --git a/UNITTESTS/features/cellular/framework/AT/at_cellulardevice/at_cellulardevicetest.cpp b/UNITTESTS/features/cellular/framework/AT/at_cellulardevice/at_cellulardevicetest.cpp index 6dc3e92a7a..af8b7107f6 100644 --- a/UNITTESTS/features/cellular/framework/AT/at_cellulardevice/at_cellulardevicetest.cpp +++ b/UNITTESTS/features/cellular/framework/AT/at_cellulardevice/at_cellulardevicetest.cpp @@ -28,22 +28,36 @@ protected: void SetUp() { + EventQueue que; + FileHandle_stub fh1; + filehandle_stub_table = NULL; + filehandle_stub_table_pos = 0; + + ATHandler at(&fh1, que, 0, ","); + ATHandler_stub::handler = &at; + + ATHandler_stub::read_string_index = kRead_string_table_size; } void TearDown() { + ATHandler_stub::handler = NULL; } }; TEST_F(TestAT_CellularDevice, Create) { FileHandle_stub fh1; + AT_CellularDevice dev(&fh1); CellularDevice *dev2 = new AT_CellularDevice(&fh1); EXPECT_TRUE(dev2 != NULL); delete dev2; + ATHandler *at = dev.get_at_handler(&fh1); + dev.release_at_handler(at); + dev.release_at_handler(at); } TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_get_at_handler) @@ -54,6 +68,7 @@ TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_get_at_handler) AT_CellularDevice dev(&fh1); // AT fh1 ref count 1 EXPECT_TRUE(dev.open_network(&fh1)); // AT fh1 ref count 2 + dev.modem_debug_on(true); EXPECT_TRUE(dev.open_sms(&fh2)); AT_CellularBase_stub::handler_value = AT_CellularBase_stub::handler_at_constructor_value; EXPECT_TRUE(dev.open_information(&fh3)); @@ -64,12 +79,12 @@ TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_get_at_handler) AT_CellularDevice *dev2 = new AT_CellularDevice(&fh1); // AT fh1 ref count 3 EXPECT_TRUE(dev2->open_information(&fh1)); // AT fh1 ref count 4 ATHandler *at = dev2->get_at_handler(); // AT fh1 ref count 5 - EXPECT_TRUE(at->get_ref_count() == 5); + EXPECT_EQ(at->get_ref_count(), 6); delete dev2; // AT fh1 2 refs deleted -> ref count 3 - EXPECT_TRUE(at->get_ref_count() == 3); + EXPECT_EQ(at->get_ref_count(), 4); AT_CellularDevice dev3(&fh1); // AT fh1 ref count 4 EXPECT_TRUE(dev3.release_at_handler(at) == NSAPI_ERROR_OK); // AT fh1 ref count 3 - EXPECT_TRUE(ATHandler_stub::ref_count == 3); + EXPECT_EQ(ATHandler_stub::ref_count, 4); } TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_open_network) @@ -118,10 +133,9 @@ TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_close_network) EXPECT_TRUE(dev.open_network(&fh1)); AT_CellularBase_stub::handler_value = AT_CellularBase_stub::handler_at_constructor_value; - EXPECT_TRUE(ATHandler_stub::ref_count == 2); + EXPECT_EQ(ATHandler_stub::ref_count, 1); dev.close_network(); - EXPECT_TRUE(ATHANDLER_REF_COUNT_AT_DESTRUCTOR == kATHandler_destructor_ref_ount); } TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_close_sms) @@ -131,10 +145,9 @@ TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_close_sms) EXPECT_TRUE(dev.open_sms(&fh1)); AT_CellularBase_stub::handler_value = AT_CellularBase_stub::handler_at_constructor_value; - EXPECT_TRUE(ATHandler_stub::ref_count == 2); + EXPECT_EQ(ATHandler_stub::ref_count, 1); dev.close_sms(); - EXPECT_TRUE(ATHANDLER_REF_COUNT_AT_DESTRUCTOR == kATHandler_destructor_ref_ount); } TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_close_information) @@ -158,7 +171,6 @@ TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_close_information) AT_CellularBase_stub::handler_value = AT_CellularBase_stub::handler_at_constructor_value; dev.close_information(); - EXPECT_TRUE(ATHANDLER_REF_COUNT_AT_DESTRUCTOR == kATHandler_destructor_ref_ount); ATHandler_stub::fh_value = NULL; } @@ -175,7 +187,7 @@ TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_set_timeout) EXPECT_TRUE(ATHandler_stub::default_timeout == true); EXPECT_TRUE(dev.open_sms(&fh1)); - EXPECT_TRUE(ATHandler_stub::ref_count == 2); + EXPECT_EQ(ATHandler_stub::ref_count, 1); dev.set_timeout(5000); EXPECT_TRUE(ATHandler_stub::timeout == 5000); @@ -194,7 +206,7 @@ TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_modem_debug_on) EXPECT_TRUE(ATHandler_stub::debug_on == true); EXPECT_TRUE(dev.open_sms(&fh1)); - EXPECT_TRUE(ATHandler_stub::ref_count == 2); + EXPECT_EQ(ATHandler_stub::ref_count, 1); dev.modem_debug_on(true); EXPECT_TRUE(ATHandler_stub::debug_on == true); @@ -268,7 +280,7 @@ TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_create_delete_context) AT_CellularDevice *dev = new AT_CellularDevice(&fh1); ATHandler *at = dev->get_at_handler(); - EXPECT_TRUE(at->get_ref_count() == 2); + EXPECT_EQ(at->get_ref_count(), 1); EXPECT_TRUE(dev->release_at_handler(at) == NSAPI_ERROR_OK); CellularContext *ctx = dev->create_context(NULL); @@ -276,12 +288,12 @@ TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_create_delete_context) dev = new AT_CellularDevice(&fh1); at = dev->get_at_handler(); - EXPECT_TRUE(at->get_ref_count() == 2); + EXPECT_EQ(at->get_ref_count(), 1); ctx = dev->create_context(NULL); CellularContext *ctx1 = dev->create_context(&fh1); - EXPECT_TRUE(at->get_ref_count() == 4); + EXPECT_EQ(at->get_ref_count(), 3); CellularContext *ctx2 = dev->create_context(&fh1); - EXPECT_TRUE(at->get_ref_count() == 5); + EXPECT_EQ(at->get_ref_count(), 4); EXPECT_TRUE(ctx); EXPECT_TRUE(ctx1); @@ -292,20 +304,20 @@ TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_create_delete_context) EXPECT_TRUE(xx); dev->delete_context(ctx); - EXPECT_TRUE(at->get_ref_count() == 4); + EXPECT_EQ(at->get_ref_count(), 3); dev->delete_context(ctx1); - EXPECT_TRUE(at->get_ref_count() == 3); + EXPECT_EQ(at->get_ref_count(), 2); dev->delete_context(NULL); - EXPECT_TRUE(at->get_ref_count() == 3); + EXPECT_EQ(at->get_ref_count(), 2); dev->delete_context(ctx2); - EXPECT_TRUE(at->get_ref_count() == 2); + EXPECT_EQ(at->get_ref_count(), 1); ctx = dev->create_context(NULL); - EXPECT_TRUE(at->get_ref_count() == 3); + EXPECT_EQ(at->get_ref_count(), 2); ctx1 = dev->create_context(&fh1); - EXPECT_TRUE(at->get_ref_count() == 4); + EXPECT_EQ(at->get_ref_count(), 3); ctx2 = dev->create_context(&fh1); - EXPECT_TRUE(at->get_ref_count() == 5); + EXPECT_EQ(at->get_ref_count(), 4); EXPECT_TRUE(dev->release_at_handler(at) == NSAPI_ERROR_OK); EXPECT_TRUE(ctx); EXPECT_TRUE(ctx1); @@ -322,6 +334,9 @@ TEST_F(TestAT_CellularDevice, TestAT_CellularDevice_set_pin_verify_debug) ATHandler at(&fh1, que, 0, ","); AT_CellularDevice *dev = new AT_CellularDevice(&fh1); + ATHandler_stub::ssize_value = 8; + ATHandler_stub::read_string_value = (char *)"internet"; + ATHandler_stub::nsapi_error_value = NSAPI_ERROR_OK; ATHandler_stub::get_debug_clear(); EXPECT_FALSE(ATHandler_stub::is_get_debug_run()); @@ -375,6 +390,9 @@ TEST_F(TestAT_CellularDevice, TestAT_CellularDevice_get_sim_state) FileHandle_stub fh1; AT_CellularDevice *dev = new AT_CellularDevice(&fh1); + ATHandler_stub::ssize_value = 8; + ATHandler_stub::read_string_value = (char *)"internet"; + CellularDevice::SimState state; ATHandler_stub::nsapi_error_value = NSAPI_ERROR_OK; ATHandler_stub::ssize_value = -1; diff --git a/UNITTESTS/features/cellular/framework/AT/at_cellulardevice/unittest.cmake b/UNITTESTS/features/cellular/framework/AT/at_cellulardevice/unittest.cmake index a529d800d7..5a4f1bd3b2 100644 --- a/UNITTESTS/features/cellular/framework/AT/at_cellulardevice/unittest.cmake +++ b/UNITTESTS/features/cellular/framework/AT/at_cellulardevice/unittest.cmake @@ -19,7 +19,6 @@ set(unittest-includes ${unittest-includes} set(unittest-sources stubs/randLIB_stub.c ../features/cellular/framework/AT/AT_CellularDevice.cpp - ../features/cellular/framework/AT/ATHandler_factory.cpp ) # Test files diff --git a/UNITTESTS/features/cellular/framework/AT/athandler/athandlertest.cpp b/UNITTESTS/features/cellular/framework/AT/athandler/athandlertest.cpp index 82d64dbcf1..d6f1e79c32 100644 --- a/UNITTESTS/features/cellular/framework/AT/athandler/athandlertest.cpp +++ b/UNITTESTS/features/cellular/framework/AT/athandler/athandlertest.cpp @@ -23,6 +23,7 @@ #include "FileHandle_stub.h" #include "CellularLog.h" #include "mbed_poll_stub.h" +#include "CellularUtil_stub.h" #include "Timer_stub.h" @@ -48,6 +49,8 @@ protected: void SetUp() { urc_callback_count = 0; + CellularUtil_stub::char_ptr = NULL; + CellularUtil_stub::char_pos = 0; } void TearDown() @@ -62,6 +65,8 @@ TEST_F(TestATHandler, Create) FileHandle_stub fh1; ATHandler *at = new ATHandler(&fh1, que, 0, ","); + at->set_default_delimiter(); + at->use_delimiter(true); delete at; @@ -774,12 +779,20 @@ TEST_F(TestATHandler, test_ATHandler_read_string) EXPECT_TRUE(!strncmp(buf4, "1016", 4)); EXPECT_TRUE(4 == at.read_string(buf4, 4 + 1/*for NULL*/)); EXPECT_TRUE(!strncmp(buf4, "39AB", 4)); + at.set_is_filehandle_usable(false); + EXPECT_TRUE(-1 == at.read_int()); + at.set_is_filehandle_usable(true); + at.clear_error(); EXPECT_TRUE(9 == at.read_int()); // *** CRLF part of the string *** at.clear_error(); char table11[] = "\"s\"\r\nOK\r\n\0"; mbed_poll_stub::int_value = 0; + at.set_is_filehandle_usable(false); + at.flush(); + at.set_is_filehandle_usable(true); + at.clear_error(); at.flush(); filehandle_stub_table = table11; filehandle_stub_table_pos = 0; @@ -840,6 +853,10 @@ TEST_F(TestATHandler, test_ATHandler_read_hex_string) char buf1[10]; // Set _stop_tag to resp_stop(OKCRLF) at.resp_start(); + char resp[] = "hello\0"; + CellularUtil_stub::char_ptr = resp; + CellularUtil_stub::char_pos = 0; + EXPECT_TRUE(5 == at.read_hex_string(buf1, 5)); EXPECT_TRUE(!strncmp(buf1, "hello", 5)); @@ -854,6 +871,7 @@ TEST_F(TestATHandler, test_ATHandler_read_hex_string) char buf2[10]; // Set _stop_tag to resp_stop(OKCRLF) at.resp_start(); + CellularUtil_stub::char_pos = 0; EXPECT_TRUE(5 == at.read_hex_string(buf2, 6)); EXPECT_TRUE(!strncmp(buf2, "hello", 5)); @@ -868,6 +886,8 @@ TEST_F(TestATHandler, test_ATHandler_read_hex_string) char buf3[6]; // Set _stop_tag to resp_stop(OKCRLF) at.resp_start(); + CellularUtil_stub::char_pos = 0; + EXPECT_TRUE(2 == at.read_hex_string(buf3, 2 + 1/*get to stop tag match*/)); EXPECT_TRUE(!strncmp(buf3, "he", 2)); at.resp_stop(); @@ -883,6 +903,8 @@ TEST_F(TestATHandler, test_ATHandler_read_hex_string) char buf4[6]; // Set _stop_tag to resp_stop(OKCRLF) at.resp_start(); + CellularUtil_stub::char_pos = 0; + EXPECT_TRUE(1 == at.read_hex_string(buf4, 2 + 1/*get to stop tag match*/)); EXPECT_TRUE(!strncmp(buf4, "h", 1)); } @@ -1278,3 +1300,84 @@ TEST_F(TestATHandler, test_ATHandler_get_3gpp_error) at.get_3gpp_error(); } +TEST_F(TestATHandler, test_ATHandler_cmd_start_stop) +{ + EventQueue que; + FileHandle_stub fh1; + + ATHandler at(&fh1, que, 0, ","); + uint8_t byte[] = {1, 2, 3, 4}; + at.cmd_start_stop("+CREG", "=1,", "%d%s%b", 3, "test", byte, 4); +} + +TEST_F(TestATHandler, test_ATHandler_at_cmd_str) +{ + EventQueue que; + FileHandle_stub fh1; + + ATHandler at(&fh1, que, 0, ","); + uint8_t byte[] = {1, 2, 3, 4}; + char ret[10]; + + char table[] = "ssssssssssssssssssssssssssssOK\r\n\0"; + filehandle_stub_table = table; + + at.flush(); + at.clear_error(); + filehandle_stub_table_pos = 0; + mbed_poll_stub::int_value = 1; + fh1.short_value = POLLIN; + + EXPECT_EQ(NSAPI_ERROR_DEVICE_ERROR, at.at_cmd_str("+CREG", "=1,", ret, 10, "%d%s%b", 3, "test", byte, 4)); +} + +TEST_F(TestATHandler, test_ATHandler_at_cmd_int) +{ + EventQueue que; + FileHandle_stub fh1; + + ATHandler at(&fh1, que, 0, ","); + uint8_t byte[] = {1, 2, 3, 4}; + int ret; + EXPECT_EQ(NSAPI_ERROR_DEVICE_ERROR, at.at_cmd_int("+CREG", "=1,", ret, "%d%s%b", 3, "test", byte, 4)); +} + +TEST_F(TestATHandler, test_ATHandler_at_cmd_discard) +{ + EventQueue que; + FileHandle_stub fh1; + + ATHandler at(&fh1, que, 0, ","); + uint8_t byte[] = {1, 2, 3, 4}; + + EXPECT_EQ(NSAPI_ERROR_DEVICE_ERROR, at.at_cmd_discard("+CREG", "=1,", "%d%s%b", 3, "test", byte, 4)); +} + +TEST_F(TestATHandler, test_ATHandler_sync) +{ + EventQueue que; + FileHandle_stub fh1; + + mbed_poll_stub::revents_value = 0; + ATHandler at(&fh1, que, 0, ","); + at.set_is_filehandle_usable(false); + EXPECT_EQ(false, at.sync(100)); + at.set_is_filehandle_usable(true); + EXPECT_EQ(false, at.sync(100)); + + fh1.size_value = 8; + char table[] = "OK\r\n\0"; + filehandle_stub_table = table; + + at.flush(); + at.clear_error(); + filehandle_stub_table_pos = 0; + mbed_poll_stub::revents_value = POLLIN + POLLOUT; + fh1.size_value = 10; + mbed_poll_stub::int_value = 1; + filehandle_stub_short_value_counter = 1; + fh1.short_value = POLLIN; + + EXPECT_EQ(true, at.sync(100)); +} + diff --git a/UNITTESTS/features/cellular/framework/AT/athandler/unittest.cmake b/UNITTESTS/features/cellular/framework/AT/athandler/unittest.cmake index 2e9dc4f1da..db74d7adc7 100644 --- a/UNITTESTS/features/cellular/framework/AT/athandler/unittest.cmake +++ b/UNITTESTS/features/cellular/framework/AT/athandler/unittest.cmake @@ -14,8 +14,6 @@ set(unittest-includes ${unittest-includes} # Source files set(unittest-sources ../features/cellular/framework/AT/ATHandler.cpp - ../features/cellular/framework/AT/ATHandler_factory.cpp - ../features/cellular/framework/common/CellularUtil.cpp ) # Test files @@ -33,6 +31,7 @@ set(unittest-test-sources stubs/Kernel_stub.cpp stubs/ThisThread_stub.cpp stubs/randLIB_stub.cpp + stubs/CellularUtil_stub.cpp ) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMBED_CONF_CELLULAR_DEBUG_AT=true -DOS_STACK_SIZE=2048") diff --git a/UNITTESTS/features/cellular/framework/device/cellularstatemachine/unittest.cmake b/UNITTESTS/features/cellular/framework/device/cellularstatemachine/unittest.cmake index 2ca63ae35c..09603bdedc 100644 --- a/UNITTESTS/features/cellular/framework/device/cellularstatemachine/unittest.cmake +++ b/UNITTESTS/features/cellular/framework/device/cellularstatemachine/unittest.cmake @@ -14,7 +14,6 @@ set(unittest-includes ${unittest-includes} # Source files set(unittest-sources ../features/cellular/framework/device/CellularStateMachine.cpp - ../features/cellular/framework/AT/ATHandler_factory.cpp ) # Test files diff --git a/UNITTESTS/stubs/ATHandler_stub.cpp b/UNITTESTS/stubs/ATHandler_stub.cpp index f888d96294..8f4038f336 100644 --- a/UNITTESTS/stubs/ATHandler_stub.cpp +++ b/UNITTESTS/stubs/ATHandler_stub.cpp @@ -25,9 +25,11 @@ using namespace events; #include "CellularLog.h" -const int DEFAULT_AT_TIMEOUT = 1000; // at default timeout in milliseconds +const int DEFAULT_AT_TIMEOUT = 1000; const uint8_t MAX_RESP_LENGTH = 7; +mbed::ATHandler *ATHandler_stub::handler = NULL; + nsapi_error_t ATHandler_stub::nsapi_error_value = 0; uint8_t ATHandler_stub::nsapi_error_ok_counter = 0; int ATHandler_stub::int_value = -1; @@ -88,8 +90,6 @@ ATHandler::ATHandler(FileHandle *fh, EventQueue &queue, uint32_t timeout, const _oobs(NULL), _max_resp_length(MAX_RESP_LENGTH) { - ATHandler_stub::ref_count = 1; - ATHandler_stub::process_oob_urc = false; } @@ -108,29 +108,21 @@ bool ATHandler::get_debug() const ATHandler::~ATHandler() { - ATHandler_stub::ref_count = kATHandler_destructor_ref_ount; - while (_oobs) { - struct oob_t *oob = _oobs; - _oobs = oob->next; - delete oob; - } } void ATHandler::inc_ref_count() { - _ref_count++; - ATHandler_stub::ref_count = _ref_count; + ATHandler_stub::ref_count++; } void ATHandler::dec_ref_count() { - _ref_count--; - ATHandler_stub::ref_count = _ref_count; + ATHandler_stub::ref_count--; } int ATHandler::get_ref_count() { - return _ref_count; + return ATHandler_stub::ref_count; } FileHandle *ATHandler::get_file_handle() @@ -145,43 +137,15 @@ void ATHandler::set_file_handle(FileHandle *fh) bool ATHandler::find_urc_handler(const char *prefix) { - struct oob_t *oob = _oobs; - while (oob) { - if (strcmp(prefix, oob->prefix) == 0) { - return true; - } - oob = oob->next; - } - - return false; + return ATHandler_stub::bool_value; } void ATHandler::set_urc_handler(const char *urc, mbed::Callback cb) { if (!cb) { - remove_urc_handler(urc); return; } - if (find_urc_handler(urc)) { - return; - } - - struct oob_t *oob = new struct oob_t; - size_t prefix_len = strlen(urc); - if (prefix_len > _oob_string_max_length) { - _oob_string_max_length = prefix_len; - if (_oob_string_max_length > _max_resp_length) { - _max_resp_length = _oob_string_max_length; - } - } - - oob->prefix = urc; - oob->prefix_len = prefix_len; - oob->cb = cb; - oob->next = _oobs; - _oobs = oob; - if (ATHandler_stub::call_immediately) { cb(); } @@ -189,21 +153,6 @@ void ATHandler::set_urc_handler(const char *urc, mbed::Callback cb) void ATHandler::remove_urc_handler(const char *prefix) { - struct oob_t *current = _oobs; - struct oob_t *prev = NULL; - while (current) { - if (strcmp(prefix, current->prefix) == 0) { - if (prev) { - prev->next = current->next; - } else { - _oobs = current->next; - } - delete current; - break; - } - prev = current; - current = prev->next; - } } nsapi_error_t ATHandler::get_last_error() const @@ -240,16 +189,6 @@ void ATHandler::restore_at_timeout() void ATHandler::process_oob() { - if (ATHandler_stub::process_oob_urc) { - size_t prefix_len = 0; - for (struct oob_t *oob = _oobs; oob; oob = oob->next) { - prefix_len = oob->prefix_len; - if (!memcmp(oob->prefix, ATHandler_stub::read_string_table[ATHandler_stub::read_string_index], prefix_len)) { - oob->cb(); - break; - } - } - } } void ATHandler::clear_error() @@ -273,7 +212,7 @@ ssize_t ATHandler::read_bytes(uint8_t *buf, size_t len) ssize_t ATHandler::read_string(char *buf, size_t size, bool read_even_stop_tag) { - + buf[0] = '\0'; if (ATHandler_stub::read_string_index == kRead_string_table_size) { if (ATHandler_stub::read_string_value && ATHandler_stub::ssize_value >= 0) { memcpy(buf, ATHandler_stub::read_string_value, ATHandler_stub::ssize_value + 1); @@ -305,7 +244,6 @@ int32_t ATHandler::read_int() return ATHandler_stub::int_value; } - //printf("ATHandler_stub::int_count: %d", ATHandler_stub::int_count); ATHandler_stub::int_count--; if (ATHandler_stub::int_count < kRead_int_table_size && ATHandler_stub::int_count >= 0) { return ATHandler_stub::int_valid_count_table[ATHandler_stub::int_count]; @@ -338,20 +276,6 @@ void ATHandler::resp_start(const char *prefix, bool stop) bool ATHandler::info_resp() { - //3 counter variables available here now so that in a test - //case it is possible to have at least two while loops checking - //specified amount of info_resps. - // - //For example: - //while(athandler.info_resp()) - //{ - // resp_info_true_counter responses handled in this loop - //} - // resp_info_false_counter set to 1 to break out from the 1st loop - //while(athandler.info_resp()) - //{ - // resp_info_true_counter2 responses handled in this loop - //} if (ATHandler_stub::resp_info_true_counter) { ATHandler_stub::resp_info_true_counter--; return true; @@ -430,3 +354,54 @@ void ATHandler::flush() { } + +nsapi_error_t ATHandler::at_cmd_str(const char *cmd, const char *cmd_chr, char *resp_buf, + size_t buf_size, const char *format, ...) +{ + read_string(resp_buf, buf_size); + return ATHandler_stub::nsapi_error_value; +} + +nsapi_error_t ATHandler::at_cmd_int(const char *cmd, const char *cmd_chr, int &resp, + const char *format, ...) +{ + resp = read_int(); + return ATHandler_stub::nsapi_error_value; +} + +void ATHandler::cmd_start_stop(const char *cmd, const char *cmd_chr, const char *format, ...) +{ +} + +nsapi_error_t ATHandler::at_cmd_discard(const char *cmd, const char *cmd_chr, + const char *format, ...) +{ + return ATHandler_stub::nsapi_error_value; +} + +ATHandler *ATHandler::get_instance(FileHandle *fileHandle, events::EventQueue &queue, uint32_t timeout, + const char *delimiter, uint16_t send_delay, bool debug_on) +{ + ATHandler_stub::ref_count++; + int a = ATHandler_stub::ref_count; + a = 0; + return ATHandler_stub::handler; +} + +nsapi_error_t ATHandler::close() +{ + ATHandler_stub::ref_count--; + return NSAPI_ERROR_OK; +} + +void ATHandler::set_at_timeout_list(uint32_t timeout_milliseconds, bool default_timeout) +{ + ATHandler_stub::timeout = timeout_milliseconds; + ATHandler_stub::default_timeout = default_timeout; +} + +void ATHandler::set_debug_list(bool debug_on) +{ + ATHandler_stub::debug_on = debug_on; +} + diff --git a/UNITTESTS/stubs/ATHandler_stub.h b/UNITTESTS/stubs/ATHandler_stub.h index 539be0d008..df3e14b3a4 100644 --- a/UNITTESTS/stubs/ATHandler_stub.h +++ b/UNITTESTS/stubs/ATHandler_stub.h @@ -26,17 +26,14 @@ #ifndef __AT_HANDLER_STUB_H__ #define __AT_HANDLER_STUB_H__ -#define ATHANDLER_REF_COUNT_AT_DESTRUCTOR -909 - static const int kRead_string_table_size = 100; static const int kRead_int_table_size = 100; static const int kResp_stop_count_default = 100; -// set reference count to -909 to separate it from zero so we can test that ATHandler is really deleted. -static const int kATHandler_destructor_ref_ount = ATHANDLER_REF_COUNT_AT_DESTRUCTOR; static const int kATHandler_urc_table_max_size = 10; static const int kATHandler_urc_string_max_size = 16; namespace ATHandler_stub { +extern mbed::ATHandler *handler; extern nsapi_error_t nsapi_error_value; extern uint8_t nsapi_error_ok_counter; extern int int_value; diff --git a/UNITTESTS/stubs/CellularUtil_stub.cpp b/UNITTESTS/stubs/CellularUtil_stub.cpp index 7de3907310..4ef142c3a5 100644 --- a/UNITTESTS/stubs/CellularUtil_stub.cpp +++ b/UNITTESTS/stubs/CellularUtil_stub.cpp @@ -19,6 +19,14 @@ #include #include #include +#include "CellularUtil_stub.h" + +int CellularUtil_stub::int_value = 0; +uint16_t CellularUtil_stub::uint16_value = 0; +char *CellularUtil_stub::char_ptr = NULL; +int CellularUtil_stub::char_pos = 0; +char *CellularUtil_stub::char_table[50] = {}; +int CellularUtil_stub::table_idx = 0; namespace mbed_cellular_util { @@ -39,7 +47,7 @@ void uint_to_binary_str(uint32_t num, char *str, uint8_t str_size, uint8_t bit_c // converts the given str to hex string to buf uint16_t char_str_to_hex(const char *str, uint16_t len, char *buf, bool omit_leading_zero) { - return 0; + return CellularUtil_stub::uint16_value; } void convert_ipv6(char *ip) @@ -49,15 +57,35 @@ void convert_ipv6(char *ip) char *find_dot_number(char *str, int dot_number) { - return NULL; + return CellularUtil_stub::char_ptr; } void separate_ip4like_addresses(char *orig, char *ip, size_t ip_size, char *ip2, size_t ip2_size) { + if (CellularUtil_stub::table_idx > 1) { + CellularUtil_stub::table_idx--; + memcpy(ip, CellularUtil_stub::char_table[CellularUtil_stub::table_idx], + strlen(CellularUtil_stub::char_table[CellularUtil_stub::table_idx])); + ip[strlen(CellularUtil_stub::char_table[CellularUtil_stub::table_idx])] = '\0'; + CellularUtil_stub::table_idx--; + memcpy(ip2, CellularUtil_stub::char_table[CellularUtil_stub::table_idx], + strlen(CellularUtil_stub::char_table[CellularUtil_stub::table_idx])); + ip2[strlen(CellularUtil_stub::char_table[CellularUtil_stub::table_idx])] = '\0'; + } } void separate_ip_addresses(char *orig, char *ip, size_t ip_size, char *ip2, size_t ip2_size) { + if (CellularUtil_stub::table_idx > 1) { + CellularUtil_stub::table_idx--; + memcpy(ip, CellularUtil_stub::char_table[CellularUtil_stub::table_idx], + strlen(CellularUtil_stub::char_table[CellularUtil_stub::table_idx])); + ip[strlen(CellularUtil_stub::char_table[CellularUtil_stub::table_idx])] = '\0'; + CellularUtil_stub::table_idx--; + memcpy(ip2, CellularUtil_stub::char_table[CellularUtil_stub::table_idx], + strlen(CellularUtil_stub::char_table[CellularUtil_stub::table_idx])); + ip2[strlen(CellularUtil_stub::char_table[CellularUtil_stub::table_idx])] = '\0'; + } } void prefer_ipv6(char *ip, size_t ip_size, char *ip2, size_t ip2_size) @@ -72,12 +100,13 @@ void int_to_hex_str(uint8_t num, char *buf) int hex_str_to_int(const char *hex_string, int hex_string_length) { - return 0; + return CellularUtil_stub::int_value; } int hex_str_to_char_str(const char *str, uint16_t len, char *buf) { - return 0; + buf[0] = CellularUtil_stub::char_ptr[CellularUtil_stub::char_pos++]; + return 1; } void uint_to_binary_str(uint32_t num, char *str, int str_size, int bit_cnt) @@ -87,28 +116,12 @@ void uint_to_binary_str(uint32_t num, char *str, int str_size, int bit_cnt) int char_str_to_hex_str(const char *str, uint16_t len, char *buf, bool omit_leading_zero) { - //The code is dependent on this, so this is easiest just to put here - if (!str || !buf) { - return 0; - } - - char *ptr = buf; - int i = 0; - while (i < len) { - if (omit_leading_zero == true && i == 0 && !(str[i] >> 4 & 0x0F)) { - *ptr++ = hex_values[(str[i]) & 0x0F]; - } else { - *ptr++ = hex_values[((str[i]) >> 4) & 0x0F]; - *ptr++ = hex_values[(str[i]) & 0x0F]; - } - i++; - } - return ptr - buf; + return CellularUtil_stub::int_value; } uint16_t get_dynamic_ip_port() { - return 0; + return CellularUtil_stub::uint16_value; } } // namespace mbed_cellular_util diff --git a/UNITTESTS/stubs/CellularUtil_stub.h b/UNITTESTS/stubs/CellularUtil_stub.h new file mode 100644 index 0000000000..9d2968daec --- /dev/null +++ b/UNITTESTS/stubs/CellularUtil_stub.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) , Arm Limited and affiliates. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CellularUtil.h" +#include +#include +#include + +namespace CellularUtil_stub { +extern int int_value; +extern uint16_t uint16_value; +extern char *char_ptr; +extern int char_pos; +extern char *char_table[50]; +extern int table_idx; + + +} // namespace mbed_cellular_util diff --git a/UNITTESTS/stubs/mbed_assert_stub.c b/UNITTESTS/stubs/mbed_assert_stub.c index afe6fb3ff3..426413a95b 100644 --- a/UNITTESTS/stubs/mbed_assert_stub.c +++ b/UNITTESTS/stubs/mbed_assert_stub.c @@ -22,3 +22,4 @@ void mbed_assert_internal(const char *expr, const char *file, int line) { fprintf(stderr, "mbed assertation failed: %s, file: %s, line %d \n", expr, file, line); } + diff --git a/features/cellular/framework/AT/ATHandler.cpp b/features/cellular/framework/AT/ATHandler.cpp index f4e756d159..1b7828666f 100644 --- a/features/cellular/framework/AT/ATHandler.cpp +++ b/features/cellular/framework/AT/ATHandler.cpp @@ -26,6 +26,8 @@ #include "rtos/ThisThread.h" #include "Kernel.h" #include "CellularUtil.h" +#include +#include "SingletonPtr.h" using namespace mbed; using namespace events; @@ -61,6 +63,104 @@ static const uint8_t map_3gpp_errors[][2] = { { 146, 46 }, { 178, 65 }, { 179, 66 }, { 180, 48 }, { 181, 83 }, { 171, 49 }, }; +ATHandler *ATHandler::_atHandlers = NULL; + +// each parser is associated with one filehandle (that is UART) +ATHandler *ATHandler::get_instance(FileHandle *fileHandle, events::EventQueue &queue, uint32_t timeout, + const char *delimiter, uint16_t send_delay, bool debug_on) +{ + if (!fileHandle) { + return NULL; + } + + singleton_lock(); + ATHandler *atHandler = _atHandlers; + while (atHandler) { + if (atHandler->get_file_handle() == fileHandle) { + atHandler->inc_ref_count(); + singleton_unlock(); + return atHandler; + } + atHandler = atHandler->_nextATHandler; + } + + atHandler = new ATHandler(fileHandle, queue, timeout, delimiter, send_delay); + if (debug_on) { + atHandler->set_debug(debug_on); + } + atHandler->_nextATHandler = _atHandlers; + _atHandlers = atHandler; + + singleton_unlock(); + return atHandler; +} + +nsapi_error_t ATHandler::close() +{ + if (get_ref_count() == 0) { + return NSAPI_ERROR_PARAMETER; + } + + singleton_lock(); + dec_ref_count(); + if (get_ref_count() == 0) { + // we can delete this at_handler + ATHandler *atHandler = _atHandlers; + ATHandler *prev = NULL; + while (atHandler) { + if (atHandler == this) { + if (prev == NULL) { + _atHandlers = _atHandlers->_nextATHandler; + } else { + prev->_nextATHandler = atHandler->_nextATHandler; + } + delete this; + break; + } else { + prev = atHandler; + atHandler = atHandler->_nextATHandler; + } + } + } + singleton_unlock(); + return NSAPI_ERROR_OK; +} + +void ATHandler::set_at_timeout_list(uint32_t timeout_milliseconds, bool default_timeout) +{ + ATHandler *atHandler = _atHandlers; + singleton_lock(); + while (atHandler) { + atHandler->set_at_timeout(timeout_milliseconds, default_timeout); + atHandler = atHandler->_nextATHandler; + } + singleton_unlock(); +} + +void ATHandler::set_debug_list(bool debug_on) +{ + ATHandler *atHandler = _atHandlers; + singleton_lock(); + while (atHandler) { + atHandler->set_debug(debug_on); + atHandler = atHandler->_nextATHandler; + } + singleton_unlock(); +} + +bool ATHandler::ok_to_proceed() +{ + if (_last_err != NSAPI_ERROR_OK) { + return false; + } + + if (!_is_fh_usable) { + _last_err = NSAPI_ERROR_BUSY; + return false; + } + return true; +} + ATHandler::ATHandler(FileHandle *fh, EventQueue &queue, uint32_t timeout, const char *output_delimiter, uint16_t send_delay) : _nextATHandler(0), _fileHandle(NULL), // filehandle is set by set_file_handle() @@ -404,12 +504,7 @@ int ATHandler::get_char() void ATHandler::skip_param(uint32_t count) { - if (_last_err || !_stop_tag || _stop_tag->found) { - return; - } - - if (!_is_fh_usable) { - _last_err = NSAPI_ERROR_BUSY; + if (!ok_to_proceed() || !_stop_tag || _stop_tag->found) { return; } @@ -438,11 +533,7 @@ void ATHandler::skip_param(uint32_t count) void ATHandler::skip_param(ssize_t len, uint32_t count) { - if (_last_err || !_stop_tag || _stop_tag->found) { - return; - } - if (!_is_fh_usable) { - _last_err = NSAPI_ERROR_BUSY; + if (!ok_to_proceed() || !_stop_tag || _stop_tag->found) { return; } @@ -462,11 +553,7 @@ void ATHandler::skip_param(ssize_t len, uint32_t count) ssize_t ATHandler::read_bytes(uint8_t *buf, size_t len) { - if (_last_err) { - return -1; - } - if (!_is_fh_usable) { - _last_err = NSAPI_ERROR_BUSY; + if (!ok_to_proceed()) { return -1; } @@ -490,11 +577,7 @@ ssize_t ATHandler::read_bytes(uint8_t *buf, size_t len) ssize_t ATHandler::read_string(char *buf, size_t size, bool read_even_stop_tag) { - if (_last_err || !_stop_tag || (_stop_tag->found && read_even_stop_tag == false)) { - return -1; - } - if (!_is_fh_usable) { - _last_err = NSAPI_ERROR_BUSY; + if (!ok_to_proceed() || !_stop_tag || (_stop_tag->found && read_even_stop_tag == false)) { return -1; } @@ -560,11 +643,7 @@ ssize_t ATHandler::read_string(char *buf, size_t size, bool read_even_stop_tag) ssize_t ATHandler::read_hex_string(char *buf, size_t size) { - if (_last_err || !_stop_tag || _stop_tag->found) { - return -1; - } - if (!_is_fh_usable) { - _last_err = NSAPI_ERROR_BUSY; + if (!ok_to_proceed() || !_stop_tag || _stop_tag->found) { return -1; } @@ -636,11 +715,7 @@ ssize_t ATHandler::read_hex_string(char *buf, size_t size) int32_t ATHandler::read_int() { - if (_last_err || !_stop_tag || _stop_tag->found) { - return -1; - } - if (!_is_fh_usable) { - _last_err = NSAPI_ERROR_BUSY; + if (!ok_to_proceed() || !_stop_tag || _stop_tag->found) { return -1; } @@ -671,7 +746,8 @@ void ATHandler::set_tag(tag_t *tag_dst, const char *tag_seq) { if (tag_seq) { size_t tag_len = strlen(tag_seq); - set_string(tag_dst->tag, tag_seq, tag_len); + memcpy(tag_dst->tag, tag_seq, tag_len); + tag_dst->tag[tag_len] = '\0'; tag_dst->len = tag_len; tag_dst->found = false; } else { @@ -899,11 +975,7 @@ void ATHandler::resp(const char *prefix, bool check_urc) void ATHandler::resp_start(const char *prefix, bool stop) { - if (_last_err) { - return; - } - if (!_is_fh_usable) { - _last_err = NSAPI_ERROR_BUSY; + if (!ok_to_proceed()) { return; } @@ -929,11 +1001,7 @@ void ATHandler::resp_start(const char *prefix, bool stop) // check urc because of error as urc bool ATHandler::info_resp() { - if (_last_err || _resp_stop.found) { - return false; - } - if (!_is_fh_usable) { - _last_err = NSAPI_ERROR_BUSY; + if (!ok_to_proceed() || _resp_stop.found) { return false; } @@ -963,11 +1031,7 @@ bool ATHandler::info_resp() bool ATHandler::info_elem(char start_tag) { - if (_last_err) { - return false; - } - if (!_is_fh_usable) { - _last_err = NSAPI_ERROR_BUSY; + if (!ok_to_proceed()) { return false; } @@ -1132,12 +1196,6 @@ ATHandler::ScopeType ATHandler::get_scope() return _current_scope; } -void ATHandler::set_string(char *dest, const char *src, size_t src_len) -{ - memcpy(dest, src, src_len); - dest[src_len] = '\0'; -} - const char *ATHandler::mem_str(const char *dest, size_t dest_len, const char *src, size_t src_len) { if (dest_len >= src_len) { @@ -1152,11 +1210,7 @@ const char *ATHandler::mem_str(const char *dest, size_t dest_len, const char *sr void ATHandler::cmd_start(const char *cmd) { - if (_last_err != NSAPI_ERROR_OK) { - return; - } - if (!_is_fh_usable) { - _last_err = NSAPI_ERROR_BUSY; + if (!ok_to_proceed()) { return; } @@ -1169,6 +1223,127 @@ void ATHandler::cmd_start(const char *cmd) _cmd_start = true; } +void ATHandler::handle_args(const char *format, va_list list) +{ + while (*format != '\0') { + if (*format == 'd') { + int i = va_arg(list, int); + write_int(i); + } else if (*format == 's') { + char *str = (char *)va_arg(list, char *); + write_string(str); + } else if (*format == 'b') { + uint8_t *bytes = va_arg(list, uint8_t *); + int size = va_arg(list, int); + write_bytes(bytes, size); + } + ++format; + } +} + +void ATHandler::handle_start(const char *cmd, const char *cmd_chr) +{ + int len = 0; + memcpy(_cmd_buffer, "AT", 2); + len += 2; + int cmd_char_len = 0; + if (cmd_chr) { + cmd_char_len = strlen(cmd_chr); + } + MBED_ASSERT((3 + strlen(cmd) + cmd_char_len) < BUFF_SIZE); + + memcpy(_cmd_buffer + len, cmd, strlen(cmd)); + len += strlen(cmd); + + if (cmd_char_len) { + memcpy(_cmd_buffer + len, cmd_chr, cmd_char_len); + len += cmd_char_len; + } + _cmd_buffer[len] = '\0'; + + const bool temp_state = get_debug(); + set_debug(true); + + cmd_start(_cmd_buffer); + + set_debug(temp_state); +} + +void ATHandler::cmd_start_stop(const char *cmd, const char *cmd_chr, const char *format, ...) +{ + handle_start(cmd, cmd_chr); + + va_list list; + va_start(list, format); + handle_args(format, list); + va_end(list); + + cmd_stop(); +} + +nsapi_error_t ATHandler::at_cmd_str(const char *cmd, const char *cmd_chr, char *resp_buf, size_t buf_size, const char *format, ...) +{ + lock(); + + handle_start(cmd, cmd_chr); + + va_list list; + va_start(list, format); + handle_args(format, list); + va_end(list); + + cmd_stop(); + + memcpy(_cmd_buffer, cmd, strlen(cmd)); + _cmd_buffer[strlen(cmd)] = ':'; + _cmd_buffer[strlen(cmd) + 1] = '\0'; + resp_start(_cmd_buffer); + + resp_buf[0] = '\0'; + read_string(resp_buf, buf_size); + resp_stop(); + return unlock_return_error(); +} + +nsapi_error_t ATHandler::at_cmd_int(const char *cmd, const char *cmd_chr, int &resp, const char *format, ...) +{ + lock(); + + handle_start(cmd, cmd_chr); + + va_list list; + va_start(list, format); + handle_args(format, list); + va_end(list); + + cmd_stop(); + char temp[16]; + size_t len = strlen(cmd); + memcpy(temp, cmd, len); + temp[len] = ':'; + temp[len + 1] = '\0'; + resp_start(temp); + + resp = read_int(); + resp_stop(); + return unlock_return_error(); +} + +nsapi_error_t ATHandler::at_cmd_discard(const char *cmd, const char *cmd_chr, const char *format, ...) +{ + lock(); + + handle_start(cmd, cmd_chr); + + va_list list; + va_start(list, format); + handle_args(format, list); + va_end(list); + + cmd_stop_read_resp(); + return unlock_return_error(); +} + void ATHandler::write_int(int32_t param) { // do common checks before sending subparameter @@ -1207,11 +1382,7 @@ void ATHandler::write_string(const char *param, bool useQuotations) void ATHandler::cmd_stop() { - if (_last_err != NSAPI_ERROR_OK) { - return; - } - if (!_is_fh_usable) { - _last_err = NSAPI_ERROR_BUSY; + if (!ok_to_proceed()) { return; } // Finish with CR @@ -1227,11 +1398,7 @@ void ATHandler::cmd_stop_read_resp() size_t ATHandler::write_bytes(const uint8_t *data, size_t len) { - if (_last_err != NSAPI_ERROR_OK) { - return 0; - } - if (!_is_fh_usable) { - _last_err = NSAPI_ERROR_BUSY; + if (!ok_to_proceed()) { return 0; } @@ -1275,25 +1442,18 @@ size_t ATHandler::write(const void *data, size_t len) // do common checks before sending subparameters bool ATHandler::check_cmd_send() { - if (_last_err != NSAPI_ERROR_OK) { + if (!ok_to_proceed()) { return false; } - if (!_is_fh_usable) { - _last_err = NSAPI_ERROR_BUSY; - return false; - } // Don't write delimiter if flag was set so - if (!_use_delimiter) { - return true; - } // Don't write delimiter if this is the first subparameter if (_cmd_start) { _cmd_start = false; } else { - if (write(&_delimiter, 1) != 1) { + if (_use_delimiter && write(&_delimiter, 1) != 1) { // writing of delimiter failed, return. write() already have set the _last_err return false; } @@ -1374,10 +1534,7 @@ bool ATHandler::sync(int timeout_ms) // especially a common response like OK could be response to previous request. clear_error(); _start_time = rtos::Kernel::get_ms_count(); - cmd_start("AT+CMEE?"); - cmd_stop(); - resp_start("+CMEE:"); - resp_stop(); + at_cmd_discard("+CMEE", "?"); if (!_last_err) { _at_timeout = timeout; unlock(); diff --git a/features/cellular/framework/AT/ATHandler.h b/features/cellular/framework/AT/ATHandler.h index 8ab5b7a8e2..13f4e955ed 100644 --- a/features/cellular/framework/AT/ATHandler.h +++ b/features/cellular/framework/AT/ATHandler.h @@ -26,6 +26,7 @@ #include "PlatformMutex.h" #include "Callback.h" +#include namespace mbed { @@ -260,6 +261,53 @@ public: */ virtual void cmd_start(const char *cmd); + /** + * @brief cmd_start_stop Starts an AT command, writes given variadic arguments and stops the command. Use this + * command when you need multiple response parameters to be handled. + * NOTE: Does not lock ATHandler for process! + * + * @param cmd AT command in form + (will be used also in response reading, no extra chars allowed) + * @param cmd_chr Char to be added to specific AT command: '?', '=' or ''. Will be used as such so '=1' is valid as well. + * @param format Format string for variadic arguments to be added to AT command; No separator needed. + * Use %d for integer, %s for string and %b for byte string (requires 2 arguments: string and length) + */ + void cmd_start_stop(const char *cmd, const char *cmd_chr, const char *format = "", ...); + + /** + * @brief at_cmd_str Send an AT command and read a single string response. Locks and unlocks ATHandler for operation + * @param cmd AT command in form + (will be used also in response reading, no extra chars allowed) + * @param cmd_chr Char to be added to specific AT command: '?', '=' or ''. Will be used as such so '=1' is valid as well. + * @param resp_buf Response buffer + * @param resp_buf_size Response buffer size + * @param format Format string for variadic arguments to be added to AT command; No separator needed. + * Use %d for integer, %s for string and %b for byte string (requires 2 arguments: string and length) + * @return last error that happened when parsing AT responses + */ + nsapi_error_t at_cmd_str(const char *cmd, const char *cmd_chr, char *resp_buf, size_t resp_buf_size, const char *format = "", ...); + + /** + * @brief at_cmd_int Send an AT command and read a single integer response. Locks and unlocks ATHandler for operation + * @param cmd AT command in form + (will be used also in response reading, no extra chars allowed) + * @param cmd_chr Char to be added to specific AT command: '?', '=' or ''. Will be used as such so '=1' is valid as well. + * @param resp Integer to hold response + * @param format Format string for variadic arguments to be added to AT command; No separator needed. + * Use %d for integer, %s for string and %b for byte string (requires 2 arguments: string and length) + * @return last error that happened when parsing AT responses + */ + nsapi_error_t at_cmd_int(const char *cmd, const char *cmd_chr, int &resp, const char *format = "", ...); + + /** + * @brief at_cmd_discard Send an AT command and read and discard a response. Locks and unlocks ATHandler for operation + * @param cmd AT command in form + (will be used also in response reading, no extra chars allowed) + * @param cmd_chr Char to be added to specific AT command: '?', '=' or ''. Will be used as such so '=1' is valid as well. + * @param format Format string for variadic arguments to be added to AT command; No separator needed. + * Use %d for integer, %s for string and %b for byte string (requires 2 arguments: string and length) + * @return last error that happened when parsing AT responses + */ + nsapi_error_t at_cmd_discard(const char *cmd, const char *cmd_chr, const char *format = "", ...); + +public: + /** Writes integer type AT command subparameter. Starts with the delimiter if not the first param after cmd_start. * In case of failure when writing, the last error is set to NSAPI_ERROR_DEVICE_ERROR. * @@ -497,6 +545,19 @@ private: // time when a command or an URC processing was started uint64_t _start_time; + char _cmd_buffer[BUFF_SIZE]; + +private: + //Handles the arguments from given variadic list + void handle_args(const char *format, va_list list); + + //Starts an AT command based on given parameters + void handle_start(const char *cmd, const char *cmd_chr); + + //Checks that ATHandler does not have a pending error condition and filehandle is usable + bool ok_to_proceed(); + +private: // Gets char from receiving buffer. // Resets and fills the buffer if all are already read (receiving position equals receiving length). // Returns a next char or -1 on failure (also sets error flag) @@ -551,15 +612,6 @@ private: bool check_cmd_send(); size_t write(const void *data, size_t len); - /** Copy content of one char buffer to another buffer and sets NULL terminator - * - * @param dest destination char buffer - * @param src source char buffer - * @param src_len number of bytes to copy - * - */ - void set_string(char *dest, const char *src, size_t src_len); - /** Finds occurrence of one char buffer inside another char buffer. * * @param dest destination char buffer diff --git a/features/cellular/framework/AT/ATHandler_factory.cpp b/features/cellular/framework/AT/ATHandler_factory.cpp deleted file mode 100644 index 0fcb42d20f..0000000000 --- a/features/cellular/framework/AT/ATHandler_factory.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2018, Arm Limited and affiliates. - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ATHandler.h" -#include "SingletonPtr.h" - -using namespace mbed; - -ATHandler *ATHandler::_atHandlers = NULL; - -// each parser is associated with one filehandle (that is UART) -ATHandler *ATHandler::get_instance(FileHandle *fileHandle, events::EventQueue &queue, uint32_t timeout, - const char *delimiter, uint16_t send_delay, bool debug_on) -{ - if (!fileHandle) { - return NULL; - } - - singleton_lock(); - ATHandler *atHandler = _atHandlers; - while (atHandler) { - if (atHandler->get_file_handle() == fileHandle) { - atHandler->inc_ref_count(); - singleton_unlock(); - return atHandler; - } - atHandler = atHandler->_nextATHandler; - } - - atHandler = new ATHandler(fileHandle, queue, timeout, delimiter, send_delay); - if (debug_on) { - atHandler->set_debug(debug_on); - } - atHandler->_nextATHandler = _atHandlers; - _atHandlers = atHandler; - - singleton_unlock(); - return atHandler; -} - -nsapi_error_t ATHandler::close() -{ - if (get_ref_count() == 0) { - return NSAPI_ERROR_PARAMETER; - } - - singleton_lock(); - dec_ref_count(); - if (get_ref_count() == 0) { - // we can delete this at_handler - ATHandler *atHandler = _atHandlers; - ATHandler *prev = NULL; - while (atHandler) { - if (atHandler == this) { - if (prev == NULL) { - _atHandlers = _atHandlers->_nextATHandler; - } else { - prev->_nextATHandler = atHandler->_nextATHandler; - } - delete this; - break; - } else { - prev = atHandler; - atHandler = atHandler->_nextATHandler; - } - } - } - singleton_unlock(); - return NSAPI_ERROR_OK; -} - -void ATHandler::set_at_timeout_list(uint32_t timeout_milliseconds, bool default_timeout) -{ - ATHandler *atHandler = _atHandlers; - singleton_lock(); - while (atHandler) { - atHandler->set_at_timeout(timeout_milliseconds, default_timeout); - atHandler = atHandler->_nextATHandler; - } - singleton_unlock(); -} - -void ATHandler::set_debug_list(bool debug_on) -{ - ATHandler *atHandler = _atHandlers; - singleton_lock(); - while (atHandler) { - atHandler->set_debug(debug_on); - atHandler = atHandler->_nextATHandler; - } - singleton_unlock(); -} diff --git a/features/cellular/framework/AT/AT_CellularContext.cpp b/features/cellular/framework/AT/AT_CellularContext.cpp index 94dd2382c8..63744275ba 100644 --- a/features/cellular/framework/AT/AT_CellularContext.cpp +++ b/features/cellular/framework/AT/AT_CellularContext.cpp @@ -302,9 +302,8 @@ nsapi_error_t AT_CellularContext::delete_current_context() { tr_info("Delete context %d", _cid); _at.clear_error(); - _at.cmd_start("AT+CGDCONT="); - _at.write_int(_cid); - _at.cmd_stop_read_resp(); + + _at.at_cmd_discard("+CGDCONT", "=", "%d", _cid); if (_at.get_last_error() == NSAPI_ERROR_OK) { _cid = -1; @@ -321,19 +320,13 @@ nsapi_error_t AT_CellularContext::do_user_authentication() if (!get_property(PROPERTY_AT_CGAUTH)) { return NSAPI_ERROR_UNSUPPORTED; } - _at.cmd_start("AT+CGAUTH="); - _at.write_int(_cid); - _at.write_int(_authentication_type); - const bool stored_debug_state = _at.get_debug(); _at.set_debug(false); - _at.write_string(_uname); - _at.write_string(_pwd); + _at.at_cmd_discard("+CGAUTH", "=", "%d%d%s%s", _cid, _authentication_type, _uname, _pwd); _at.set_debug(stored_debug_state); - _at.cmd_stop_read_resp(); if (_at.get_last_error() != NSAPI_ERROR_OK) { return NSAPI_ERROR_AUTH_FAILURE; } @@ -360,8 +353,8 @@ bool AT_CellularContext::get_context() { bool modem_supports_ipv6 = get_property(PROPERTY_IPV6_PDP_TYPE); bool modem_supports_ipv4 = get_property(PROPERTY_IPV4_PDP_TYPE); - _at.cmd_start("AT+CGDCONT?"); - _at.cmd_stop(); + + _at.cmd_start_stop("+CGDCONT", "?"); _at.resp_start("+CGDCONT:"); _cid = -1; int cid_max = 0; // needed when creating new context @@ -438,13 +431,8 @@ bool AT_CellularContext::set_new_context(int cid) } //apn: "If the value is null or omitted, then the subscription value will be requested." - bool success = false; - _at.cmd_start("AT+CGDCONT="); - _at.write_int(cid); - _at.write_string(pdp_type_str); - _at.write_string(_apn); - _at.cmd_stop_read_resp(); - success = (_at.get_last_error() == NSAPI_ERROR_OK); + + bool success = (_at.at_cmd_discard("+CGDCONT", "=", "%d%s%s", cid, pdp_type_str, _apn) == NSAPI_ERROR_OK); if (success) { _pdp_type = pdp_type; @@ -481,9 +469,7 @@ nsapi_error_t AT_CellularContext::activate_non_ip_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(); + _at.at_cmd_discard("+CGACT", "=1,", "%d", _cid); if (_at.get_last_error() == NSAPI_ERROR_OK) { _is_context_activated = true; } @@ -590,8 +576,7 @@ nsapi_error_t AT_CellularContext::open_data_channel() tr_info("CellularContext PPP connect"); if (get_property(PROPERTY_AT_CGDATA)) { - _at.cmd_start("AT+CGDATA=\"PPP\","); - _at.write_int(_cid); + _at.cmd_start_stop("+CGDATA", "=\"PPP\",", "%d", _cid); } else { MBED_ASSERT(_cid >= 0 && _cid <= 99); _at.cmd_start("ATD*99***"); @@ -599,8 +584,8 @@ nsapi_error_t AT_CellularContext::open_data_channel() _at.write_int(_cid); _at.write_string("#", false); _at.use_delimiter(true); + _at.cmd_stop(); } - _at.cmd_stop(); _at.resp_start("CONNECT", true); if (_at.get_last_error()) { @@ -733,9 +718,7 @@ void AT_CellularContext::deactivate_non_ip_context() void AT_CellularContext::deactivate_context() { - _at.cmd_start("AT+CGACT=0,"); - _at.write_int(_cid); - _at.cmd_stop_read_resp(); + _at.at_cmd_discard("+CGACT", "=0,", "%d", _cid); } void AT_CellularContext::check_and_deactivate_context() @@ -759,9 +742,7 @@ void AT_CellularContext::check_and_deactivate_context() if (_new_context_set) { _at.clear_error(); - _at.cmd_start("AT+CGDCONT="); - _at.write_int(_cid); - _at.cmd_stop_read_resp(); + _at.at_cmd_discard("+CGDCONT", "=", "%d", _cid); } _at.restore_at_timeout(); @@ -772,9 +753,7 @@ nsapi_error_t AT_CellularContext::get_apn_backoff_timer(int &backoff_timer) // If apn is set if (_apn) { _at.lock(); - _at.cmd_start("AT+CABTRDP="); - _at.write_string(_apn); - _at.cmd_stop(); + _at.cmd_start_stop("+CABTRDP", "=", "%s", _apn); _at.resp_start("+CABTRDP:"); if (_at.info_resp()) { _at.skip_param(); @@ -792,10 +771,7 @@ nsapi_error_t AT_CellularContext::get_rate_control( CellularContext::RateControlUplinkTimeUnit &timeUnit, int &uplinkRate) { _at.lock(); - - _at.cmd_start("AT+CGAPNRC="); - _at.write_int(_cid); - _at.cmd_stop(); + _at.cmd_start_stop("+CGAPNRC", "=", "%d", _cid); _at.resp_start("+CGAPNRC:"); _at.read_int(); @@ -837,9 +813,7 @@ nsapi_error_t AT_CellularContext::get_pdpcontext_params(pdpContextList_t ¶ms _at.lock(); - _at.cmd_start("AT+CGCONTRDP="); - _at.write_int(_cid); - _at.cmd_stop(); + _at.cmd_start_stop("+CGCONTRDP", "=", "%d", _cid); _at.resp_start("+CGCONTRDP:"); pdpcontext_params_t *params = NULL; diff --git a/features/cellular/framework/AT/AT_CellularDevice.cpp b/features/cellular/framework/AT/AT_CellularDevice.cpp index 86676ebafc..52cccfaae4 100644 --- a/features/cellular/framework/AT/AT_CellularDevice.cpp +++ b/features/cellular/framework/AT/AT_CellularDevice.cpp @@ -184,10 +184,10 @@ nsapi_error_t AT_CellularDevice::get_sim_state(SimState &state) char simstr[MAX_SIM_RESPONSE_LENGTH]; _at->lock(); _at->flush(); - _at->cmd_start("AT+CPIN?"); - _at->cmd_stop(); - _at->resp_start("+CPIN:"); - ssize_t len = _at->read_string(simstr, sizeof(simstr)); + nsapi_error_t error = _at->at_cmd_str("+CPIN", "?", simstr, sizeof(simstr)); + ssize_t len = strlen(simstr); + _at->unlock(); + if (len != -1) { if (len >= 5 && memcmp(simstr, "READY", 5) == 0) { state = SimStateReady; @@ -204,9 +204,6 @@ nsapi_error_t AT_CellularDevice::get_sim_state(SimState &state) tr_warn("SIM not readable."); state = SimStateUnknown; // SIM may not be ready yet or +CPIN may be unsupported command } - _at->resp_stop(); - nsapi_error_t error = _at->get_last_error(); - _at->unlock(); #if MBED_CONF_MBED_TRACE_ENABLE switch (state) { case SimStatePinNeeded: @@ -230,7 +227,7 @@ nsapi_error_t AT_CellularDevice::set_pin(const char *sim_pin) { // if SIM is already in ready state then settings the PIN // will return error so let's check the state before settings the pin. - SimState state; + SimState state = SimStateUnknown; if (get_sim_state(state) == NSAPI_ERROR_OK && state == SimStateReady) { return NSAPI_ERROR_OK; } @@ -240,16 +237,14 @@ nsapi_error_t AT_CellularDevice::set_pin(const char *sim_pin) } _at->lock(); - _at->cmd_start("AT+CPIN="); const bool stored_debug_state = _at->get_debug(); _at->set_debug(false); - _at->write_string(sim_pin); + _at->at_cmd_discard("+CPIN", "=,", "%s", sim_pin); _at->set_debug(stored_debug_state); - _at->cmd_stop_read_resp(); return _at->unlock_return_error(); } @@ -431,41 +426,34 @@ nsapi_error_t AT_CellularDevice::init() { _at->lock(); _at->flush(); - _at->cmd_start("ATE0"); // echo off - _at->cmd_stop_read_resp(); + _at->at_cmd_discard("E0", ""); - _at->cmd_start("AT+CMEE=1"); // verbose responses - _at->cmd_stop_read_resp(); + _at->at_cmd_discard("+CMEE", "=1"); - _at->cmd_start("AT+CFUN=1"); // set full functionality - _at->cmd_stop_read_resp(); + _at->at_cmd_discard("+CFUN", "=1"); return _at->unlock_return_error(); } nsapi_error_t AT_CellularDevice::shutdown() { - _at->lock(); if (_state_machine) { _state_machine->reset(); } CellularDevice::shutdown(); - _at->cmd_start("AT+CFUN=0");// set to minimum functionality - _at->cmd_stop_read_resp(); - return _at->unlock_return_error(); + + return _at->at_cmd_discard("+CFUN", "=0"); } nsapi_error_t AT_CellularDevice::is_ready() { _at->lock(); - _at->cmd_start("AT"); - _at->cmd_stop_read_resp(); + _at->at_cmd_discard("", ""); // we need to do this twice because for example after data mode the first 'AT' command will give modem a // stimulus that we are back to command mode. _at->clear_error(); - _at->cmd_start("AT"); - _at->cmd_stop_read_resp(); + _at->at_cmd_discard("", ""); return _at->unlock_return_error(); } @@ -480,9 +468,7 @@ nsapi_error_t AT_CellularDevice::set_power_save_mode(int periodic_time, int acti if (periodic_time == 0 && active_time == 0) { // disable PSM - _at->cmd_start("AT+CPSMS="); - _at->write_int(0); - _at->cmd_stop_read_resp(); + _at->at_cmd_discard("+CPSMS", "=0"); } else { const int PSMTimerBits = 5; @@ -583,13 +569,8 @@ nsapi_error_t AT_CellularDevice::set_power_save_mode(int periodic_time, int acti at[8] = '\0'; // request for both GPRS and LTE - _at->cmd_start("AT+CPSMS="); - _at->write_int(1); - _at->write_string(pt); - _at->write_string(at); - _at->write_string(pt); - _at->write_string(at); - _at->cmd_stop_read_resp(); + + _at->at_cmd_discard("+CPSMS", "=1,", "%s%s%s%s", pt, at, pt, at); if (_at->get_last_error() != NSAPI_ERROR_OK) { tr_warn("Power save mode not enabled!"); diff --git a/features/cellular/framework/AT/AT_CellularInformation.cpp b/features/cellular/framework/AT/AT_CellularInformation.cpp index 331896da2e..431884bdca 100644 --- a/features/cellular/framework/AT/AT_CellularInformation.cpp +++ b/features/cellular/framework/AT/AT_CellularInformation.cpp @@ -58,14 +58,7 @@ nsapi_error_t AT_CellularInformation::get_serial_number(char *buf, size_t buf_si return NSAPI_ERROR_UNSUPPORTED; } - _at.lock(); - _at.cmd_start("AT+CGSN="); - _at.write_int(type); - _at.cmd_stop(); - _at.resp_start("+CGSN:"); - _at.read_string(buf, buf_size); - _at.resp_stop(); - return _at.unlock_return_error(); + return _at.at_cmd_str("+CGSN", "=", buf, buf_size, "%d", type); } nsapi_error_t AT_CellularInformation::get_info(const char *cmd, char *buf, size_t buf_size) @@ -103,11 +96,5 @@ nsapi_error_t AT_CellularInformation::get_iccid(char *buf, size_t buf_size) if (buf == NULL || buf_size == 0) { return NSAPI_ERROR_PARAMETER; } - _at.lock(); - _at.cmd_start("AT+CCID?"); - _at.cmd_stop(); - _at.resp_start("+CCID:"); - _at.read_string(buf, buf_size); - _at.resp_stop(); - return _at.unlock_return_error(); + return _at.at_cmd_str("+CCID", "?", buf, buf_size); } diff --git a/features/cellular/framework/AT/AT_CellularNetwork.cpp b/features/cellular/framework/AT/AT_CellularNetwork.cpp index 9b7f53b8b6..7000e06707 100644 --- a/features/cellular/framework/AT/AT_CellularNetwork.cpp +++ b/features/cellular/framework/AT/AT_CellularNetwork.cpp @@ -32,9 +32,9 @@ struct at_reg_t { }; static const at_reg_t at_reg[] = { - { CellularNetwork::C_EREG, "AT+CEREG", "+CEREG:"}, - { CellularNetwork::C_GREG, "AT+CGREG", "+CGREG:"}, - { CellularNetwork::C_REG, "AT+CREG", "+CREG:"} + { CellularNetwork::C_EREG, "+CEREG", "+CEREG:"}, + { CellularNetwork::C_GREG, "+CGREG", "+CGREG:"}, + { CellularNetwork::C_REG, "+CREG", "+CREG:"} }; #if MBED_CONF_MBED_TRACE_ENABLE @@ -189,61 +189,42 @@ nsapi_error_t AT_CellularNetwork::set_registration_urc(RegistrationType type, bo if (mode == RegistrationModeDisable) { return NSAPI_ERROR_UNSUPPORTED; } else { - _at.lock(); if (urc_on) { - _at.cmd_start(at_reg[index].cmd); - const uint8_t ch_eq = '='; - _at.write_bytes(&ch_eq, 1); - _at.write_int((int)mode); + return _at.at_cmd_discard(at_reg[index].cmd, "=", "%d", mode); } else { - _at.cmd_start(at_reg[index].cmd); - _at.write_string("=0", false); + return _at.at_cmd_discard(at_reg[index].cmd, "=0"); } - - _at.cmd_stop_read_resp(); - return _at.unlock_return_error(); } } nsapi_error_t AT_CellularNetwork::get_network_registering_mode(NWRegisteringMode &mode) { - _at.lock(); - _at.cmd_start("AT+COPS?"); - _at.cmd_stop(); - _at.resp_start("+COPS:"); - mode = (NWRegisteringMode)_at.read_int(); - _at.resp_stop(); - - return _at.unlock_return_error(); + int ret; + nsapi_error_t error = _at.at_cmd_int("+COPS", "?", ret); + mode = (NWRegisteringMode)ret; + return error; } nsapi_error_t AT_CellularNetwork::set_registration(const char *plmn) { - _at.lock(); if (!plmn) { tr_debug("Automatic network registration"); - _at.cmd_start("AT+COPS?"); - _at.cmd_stop(); - _at.resp_start("+COPS:"); - int mode = _at.read_int(); - _at.resp_stop(); - if (mode != 0) { - _at.clear_error(); - _at.cmd_start("AT+COPS=0"); - _at.cmd_stop_read_resp(); + NWRegisteringMode mode; + get_network_registering_mode(mode); + + if (mode != NWModeAutomatic) { + return _at.at_cmd_discard("+COPS", "=0"); } + return NSAPI_ERROR_OK; } else { tr_debug("Manual network registration to %s", plmn); - _at.cmd_start("AT+COPS=1,2,"); - _at.write_string(plmn); if (_op_act != RAT_UNKNOWN) { - _at.write_int(_op_act); + return _at.at_cmd_discard("+COPS", "=1,2,", "%s%d", plmn, _op_act); + } else { + return _at.at_cmd_discard("+COPS", "=1,2", "%s", plmn); } - _at.cmd_stop_read_resp(); } - - return _at.unlock_return_error(); } void AT_CellularNetwork::read_reg_params(RegistrationType type, registration_params_t ®_params) @@ -290,16 +271,12 @@ void AT_CellularNetwork::read_reg_params(RegistrationType type, registration_par nsapi_error_t AT_CellularNetwork::set_attach() { _at.lock(); + AttachStatus status; + get_attach(status); - _at.cmd_start("AT+CGATT?"); - _at.cmd_stop(); - _at.resp_start("+CGATT:"); - int attached_state = _at.read_int(); - _at.resp_stop(); - if (attached_state != 1) { + if (status == Detached) { tr_debug("Network attach"); - _at.cmd_start("AT+CGATT=1"); - _at.cmd_stop_read_resp(); + _at.at_cmd_discard("+CGATT", "=1"); } return _at.unlock_return_error(); @@ -307,31 +284,19 @@ nsapi_error_t AT_CellularNetwork::set_attach() nsapi_error_t AT_CellularNetwork::get_attach(AttachStatus &status) { - _at.lock(); + int attach_status; + nsapi_error_t err = _at.at_cmd_int("+CGATT", "?", attach_status); + status = (attach_status == 1) ? Attached : Detached; - _at.cmd_start("AT+CGATT?"); - _at.cmd_stop(); - - _at.resp_start("+CGATT:"); - if (_at.info_resp()) { - int attach_status = _at.read_int(); - status = (attach_status == 1) ? Attached : Detached; - } - _at.resp_stop(); - - return _at.unlock_return_error(); + return err; } nsapi_error_t AT_CellularNetwork::detach() { - _at.lock(); - tr_debug("Network detach"); - _at.cmd_start("AT+CGATT=0"); - _at.cmd_stop_read_resp(); + _at.at_cmd_discard("+CGATT", "=0"); - _at.cmd_start("AT+COPS=2"); - _at.cmd_stop_read_resp(); + _at.at_cmd_discard("+COPS", "=2"); call_network_cb(NSAPI_STATUS_DISCONNECTED); @@ -361,8 +326,7 @@ nsapi_error_t AT_CellularNetwork::scan_plmn(operList_t &operators, int &opsCount _at.lock(); - _at.cmd_start("AT+COPS=?"); - _at.cmd_stop(); + _at.cmd_start_stop("+COPS", "=?"); _at.resp_start("+COPS:"); @@ -400,15 +364,7 @@ nsapi_error_t AT_CellularNetwork::set_ciot_optimization_config(CIoT_Supported_Op Callback network_support_cb) { _ciotopt_network_support_cb = network_support_cb; - _at.lock(); - - _at.cmd_start("AT+CCIOTOPT="); - _at.write_int(1); //enable CCIOTOPTI URC - _at.write_int(supported_opt); - _at.write_int(preferred_opt); - _at.cmd_stop_read_resp(); - - return _at.unlock_return_error(); + return _at.at_cmd_discard("+CCIOTOPT", "=1,", "%d%d", supported_opt, preferred_opt); } void AT_CellularNetwork::urc_cciotopti() @@ -425,8 +381,7 @@ nsapi_error_t AT_CellularNetwork::get_ciot_ue_optimization_config(CIoT_Supported { _at.lock(); - _at.cmd_start("AT+CCIOTOPT?"); - _at.cmd_stop(); + _at.cmd_start_stop("+CCIOTOPT", "?"); _at.resp_start("+CCIOTOPT:"); _at.read_int(); @@ -450,8 +405,7 @@ nsapi_error_t AT_CellularNetwork::get_signal_quality(int &rssi, int *ber) { _at.lock(); - _at.cmd_start("AT+CSQ"); - _at.cmd_stop(); + _at.cmd_start_stop("+CSQ", ""); _at.resp_start("+CSQ:"); int t_rssi = _at.read_int(); @@ -492,8 +446,7 @@ nsapi_error_t AT_CellularNetwork::get_operator_params(int &format, operator_t &o { _at.lock(); - _at.cmd_start("AT+COPS?"); - _at.cmd_stop(); + _at.cmd_start_stop("+COPS", "?"); _at.resp_start("+COPS:"); _at.read_int(); //ignore mode @@ -523,8 +476,7 @@ nsapi_error_t AT_CellularNetwork::get_operator_names(operator_names_list &op_nam { _at.lock(); - _at.cmd_start("AT+COPN"); - _at.cmd_stop(); + _at.cmd_start_stop("+COPN", ""); _at.resp_start("+COPN:"); operator_names_t *names = NULL; @@ -540,8 +492,7 @@ nsapi_error_t AT_CellularNetwork::get_operator_names(operator_names_list &op_nam void AT_CellularNetwork::get_context_state_command() { - _at.cmd_start("AT+CGACT?"); - _at.cmd_stop(); + _at.cmd_start_stop("+CGACT", "?"); _at.resp_start("+CGACT:"); } @@ -597,12 +548,9 @@ nsapi_error_t AT_CellularNetwork::get_registration_params(RegistrationType type, _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]); + _at.cmd_start_stop(at_reg[i].cmd, "?"); + _at.resp_start(at_reg[i].urc_prefix); (void)_at.read_int(); // ignore urc mode subparam read_reg_params(type, reg_params); _at.resp_stop(); @@ -670,15 +618,7 @@ nsapi_error_t AT_CellularNetwork::set_receive_period(int mode, EDRXAccessTechnol uint_to_binary_str(edrx_value, edrx, 5, 4); edrx[4] = '\0'; - _at.lock(); - - _at.cmd_start("AT+CEDRXS="); - _at.write_int(mode); - _at.write_int(act_type); - _at.write_string(edrx); - _at.cmd_stop_read_resp(); - - return _at.unlock_return_error(); + return _at.at_cmd_discard("+CEDRXS", "=", "%d%d%s", mode, act_type, edrx); } nsapi_error_t AT_CellularNetwork::set_packet_domain_event_reporting(bool on) @@ -687,10 +627,5 @@ nsapi_error_t AT_CellularNetwork::set_packet_domain_event_reporting(bool on) return NSAPI_ERROR_UNSUPPORTED; } - _at.lock(); - _at.cmd_start("AT+CGEREP="); - _at.write_int(on ? 1 : 0); // discard unsolicited result codes when MT TE link is reserved (e.g. in on line data mode); otherwise forward them directly to the TE - _at.cmd_stop_read_resp(); - - return _at.unlock_return_error(); + return _at.at_cmd_discard("+CGEREP", "=", "%d", on ? 1 : 0); } diff --git a/features/cellular/framework/AT/AT_CellularSMS.cpp b/features/cellular/framework/AT/AT_CellularSMS.cpp index 435f513812..dd30b4dd2e 100644 --- a/features/cellular/framework/AT/AT_CellularSMS.cpp +++ b/features/cellular/framework/AT/AT_CellularSMS.cpp @@ -213,10 +213,8 @@ nsapi_error_t AT_CellularSMS::set_cnmi() if (!get_property(PROPERTY_AT_CNMI)) { return NSAPI_ERROR_UNSUPPORTED; } - _at.lock(); - _at.cmd_start("AT+CNMI=2,1"); - _at.cmd_stop_read_resp(); - return _at.unlock_return_error(); + + return _at.at_cmd_discard("+CNMI", "=2,1"); } nsapi_error_t AT_CellularSMS::set_cmgf(int msg_format) @@ -224,11 +222,8 @@ nsapi_error_t AT_CellularSMS::set_cmgf(int msg_format) if (!get_property(PROPERTY_AT_CMGF)) { return NSAPI_ERROR_UNSUPPORTED; } - _at.lock(); - _at.cmd_start("AT+CMGF="); - _at.write_int(msg_format); - _at.cmd_stop_read_resp(); - return _at.unlock_return_error(); + + return _at.at_cmd_discard("+CMGF", "=", "%d", msg_format); } nsapi_error_t AT_CellularSMS::set_csmp(int fo, int vp, int pid, int dcs) @@ -236,14 +231,8 @@ nsapi_error_t AT_CellularSMS::set_csmp(int fo, int vp, int pid, int dcs) if (!get_property(PROPERTY_AT_CSMP)) { return NSAPI_ERROR_UNSUPPORTED; } - _at.lock(); - _at.cmd_start("AT+CSMP="); - _at.write_int(fo); - _at.write_int(vp); - _at.write_int(pid); - _at.write_int(dcs); - _at.cmd_stop_read_resp(); - return _at.unlock_return_error(); + + return _at.at_cmd_discard("+CSMP", "=", "%d%d%d%d", fo, vp, pid, dcs); } nsapi_error_t AT_CellularSMS::set_csdh(int show_header) @@ -251,11 +240,8 @@ nsapi_error_t AT_CellularSMS::set_csdh(int show_header) if (!get_property(PROPERTY_AT_CSDH)) { return NSAPI_ERROR_UNSUPPORTED; } - _at.lock(); - _at.cmd_start("AT+CSDH="); - _at.write_int(show_header); - _at.cmd_stop_read_resp(); - return _at.unlock_return_error(); + + return _at.at_cmd_discard("+CSDH", "=", "%d", show_header); } nsapi_error_t AT_CellularSMS::initialize(CellularSMSMmode mode) @@ -408,7 +394,8 @@ char *AT_CellularSMS::create_pdu(const char *phone_number, const char *message, nsapi_size_or_error_t AT_CellularSMS::send_sms(const char *phone_number, const char *message, int msg_len) { - int single_sms_max_length = _use_8bit_encoding ? SMS_MAX_SIZE_8BIT_SINGLE_SMS_SIZE : + int single_sms_max_length = _use_8bit_encoding ? + SMS_MAX_SIZE_8BIT_SINGLE_SMS_SIZE : SMS_MAX_SIZE_GSM7_SINGLE_SMS_SIZE; if ((_mode == CellularSMSMmodeText && msg_len > single_sms_max_length) || !phone_number) { return NSAPI_ERROR_PARAMETER; @@ -422,9 +409,7 @@ nsapi_size_or_error_t AT_CellularSMS::send_sms(const char *phone_number, const c wait_ms(_sim_wait_time); if (_mode == CellularSMSMmodeText) { - _at.cmd_start("AT+CMGS="); - _at.write_string(phone_number + remove_plus_sign); - _at.cmd_stop(); + _at.cmd_start_stop("+CMGS", "=", "%s", phone_number + remove_plus_sign); wait_ms(_sim_wait_time); _at.resp_start("> ", true); @@ -448,7 +433,8 @@ nsapi_size_or_error_t AT_CellularSMS::send_sms(const char *phone_number, const c // supports uncompressed 8 bit data and GSM 7 bit default alphabet data. Current implementation uses only // GSM 7 bit default but support is done for 8 bit data. int sms_count; - int concatenated_sms_length = _use_8bit_encoding ? SMS_MAX_8BIT_CONCATENATED_SINGLE_SMS_SIZE : + int concatenated_sms_length = _use_8bit_encoding ? + SMS_MAX_8BIT_CONCATENATED_SINGLE_SMS_SIZE : SMS_MAX_GSM7_CONCATENATED_SINGLE_SMS_SIZE; if (msg_len <= single_sms_max_length) { @@ -485,9 +471,8 @@ nsapi_size_or_error_t AT_CellularSMS::send_sms(const char *phone_number, const c pdu_len = strlen(pdu_str); // specification says that service center number should not be included so we subtract -2 from pdu_len as we use '00' for automatic service center number - _at.cmd_start("AT+CMGS="); - _at.write_int((pdu_len - 2) / 2); - _at.cmd_stop(); + + _at.cmd_start_stop("+CMGS", "=", "%d", (pdu_len - 2) / 2); wait_ms(_sim_wait_time); _at.resp_start("> ", true); @@ -540,44 +525,24 @@ void AT_CellularSMS::set_sms_callback(Callback func) nsapi_error_t AT_CellularSMS::set_cpms(const char *memr, const char *memw, const char *mems) { - _at.lock(); - _at.cmd_start("AT+CPMS="); - _at.write_string(memr); - _at.write_string(memw); - _at.write_string(mems); - _at.cmd_stop_read_resp(); - - return _at.unlock_return_error(); + return _at.at_cmd_discard("+CPMS", "=", "%s%s%s", memr, memw, mems); } nsapi_error_t AT_CellularSMS::set_csca(const char *sca, int type) { - _at.lock(); - _at.cmd_start("AT+CSCA="); - _at.write_string(sca); - _at.write_int(type); - _at.cmd_stop_read_resp(); - - return _at.unlock_return_error(); + return _at.at_cmd_discard("+CSCA", "=", "%s%d", sca, type); } nsapi_size_or_error_t AT_CellularSMS::set_cscs(const char *chr_set) { - _at.lock(); - _at.cmd_start("AT+CSCS="); - _at.write_string(chr_set); - _at.cmd_stop_read_resp(); - - return _at.unlock_return_error(); + return _at.at_cmd_discard("+CSCS", "=", "%s", chr_set); } nsapi_error_t AT_CellularSMS::delete_sms(sms_info_t *sms) { _at.lock(); for (int i = 0; i < sms->parts; i++) { - _at.cmd_start("AT+CMGD="); - _at.write_int(sms->msg_index[i]); - _at.cmd_stop_read_resp(); + _at.at_cmd_discard("+CMGD", "=", "%d", sms->msg_index[i]); } return _at.unlock_return_error(); @@ -589,10 +554,7 @@ nsapi_error_t AT_CellularSMS::delete_sms(sms_info_t *sms) // that was corrupted. So we need to have delete all messages. nsapi_error_t AT_CellularSMS::delete_all_messages() { - _at.lock(); - _at.cmd_start("AT+CMGD=1,4"); - _at.cmd_stop_read_resp(); - return _at.unlock_return_error(); + return _at.at_cmd_discard("+CMGD", "=1,4"); } // read msg in text mode @@ -603,9 +565,7 @@ nsapi_size_or_error_t AT_CellularSMS::read_sms_from_index(int msg_index, char *b * +CMGR: ,,,[,,,,,,,]OK */ wait_ms(_sim_wait_time); - _at.cmd_start("AT+CMGR="); - _at.write_int(msg_index); - _at.cmd_stop(); + _at.cmd_start_stop("+CMGR", "=", "%d", msg_index); // TODO: NOTE: If the selected can contain different types of SMs (e.g. SMS-DELIVERs, SMS-SUBMITs, SMS-STATUS-REPORTs and SMS-COMMANDs), // the response may be a mix of the responses of different SM types. TE application can recognize the response format by examining the third response parameter. @@ -662,9 +622,7 @@ nsapi_size_or_error_t AT_CellularSMS::read_sms(sms_info_t *sms, char *buf, char for (int i = 0; i < sms->parts; i++) { wait_ms(_sim_wait_time); - _at.cmd_start("AT+CMGR="); - _at.write_int(sms->msg_index[i]); - _at.cmd_stop(); + _at.cmd_start_stop("+CMGR", "=", "%d", sms->msg_index[i]); _at.resp_start("+CMGR:"); if (_at.info_resp()) { @@ -1041,11 +999,10 @@ nsapi_error_t AT_CellularSMS::list_messages() // the response may be a mix of the responses of different SM types. TE application can recognize the response format by examining the third response parameter. // for now we assume that only SMS-DELIVER messages are read. if (_mode == CellularSMSMmodePDU) { - _at.cmd_start("AT+CMGL=4"); + _at.cmd_start_stop("+CMGL", "=4"); } else { - _at.cmd_start("AT+CMGL=\"ALL\""); + _at.cmd_start_stop("+CMGL", "=\"ALL\""); } - _at.cmd_stop(); sms_info_t *info = NULL; // init for 1 so that in text mode we will add to the correct place without any additional logic in addInfo() in text mode diff --git a/features/cellular/framework/AT/AT_CellularStack.cpp b/features/cellular/framework/AT/AT_CellularStack.cpp index 0939d82343..31417a98d8 100644 --- a/features/cellular/framework/AT/AT_CellularStack.cpp +++ b/features/cellular/framework/AT/AT_CellularStack.cpp @@ -59,9 +59,7 @@ const char *AT_CellularStack::get_ip_address() { _at.lock(); - _at.cmd_start("AT+CGPADDR="); - _at.write_int(_cid); - _at.cmd_stop(); + _at.cmd_start_stop("+CGPADDR", "=", "%d", _cid); _at.resp_start("+CGPADDR:"); diff --git a/features/cellular/framework/AT/AT_ControlPlane_netif.cpp b/features/cellular/framework/AT/AT_ControlPlane_netif.cpp index 0ed38f5fa0..882c5d2d8e 100644 --- a/features/cellular/framework/AT/AT_ControlPlane_netif.cpp +++ b/features/cellular/framework/AT/AT_ControlPlane_netif.cpp @@ -34,12 +34,10 @@ nsapi_size_or_error_t AT_ControlPlane_netif::send(const void *cpdata, nsapi_size { //CSODCP _at.lock(); - _at.cmd_start("AT+CSODCP="); - _at.write_int(_cid); - _at.write_int(cpdata_length); - _at.write_bytes((uint8_t *)cpdata, cpdata_length); - return _at.unlock_return_error(); + nsapi_size_or_error_t err = _at.at_cmd_discard("+CSODCP", "=", "%d%d%b", _cid, cpdata_length, cpdata, cpdata_length); + + return (err == NSAPI_ERROR_OK) ? cpdata_length : err; } nsapi_size_or_error_t AT_ControlPlane_netif::recv(void *cpdata, nsapi_size_t cpdata_length) @@ -55,8 +53,9 @@ nsapi_size_or_error_t AT_ControlPlane_netif::recv(void *cpdata, nsapi_size_t cpd } memcpy(cpdata, _recv_buffer, _recv_len); - - return _recv_len = 0; + size_t recv = _recv_len; + _recv_len = 0; + return recv; } void AT_ControlPlane_netif::attach(void (*callback)(void *), void *data) 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 de9194da6b..ba0a90f4e1 100644 --- a/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularContext.cpp +++ b/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularContext.cpp @@ -70,17 +70,8 @@ ControlPlane_netif *QUECTEL_BG96_CellularContext::get_cp_netif() nsapi_error_t QUECTEL_BG96_CellularContext::do_user_authentication() { if (_pwd && _uname) { - _at.cmd_start("AT+QICSGP="); - _at.write_int(_cid); - _at.write_int(1); // IPv4 - _at.write_string(_apn); - _at.write_string(_uname); - _at.write_string(_pwd); - _at.write_int(_authentication_type); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); - if (_at.get_last_error() != NSAPI_ERROR_OK) { + if (_at.at_cmd_discard("+QICSGP", "=", "%d%d%s%s%s%d", _cid, 1, + _apn, _uname, _pwd, _authentication_type) != NSAPI_ERROR_OK) { return NSAPI_ERROR_AUTH_FAILURE; } } @@ -90,17 +81,9 @@ nsapi_error_t QUECTEL_BG96_CellularContext::do_user_authentication() nsapi_error_t QUECTEL_BG96_CellularContext::activate_non_ip_context() { - _at.lock(); // Open the NIDD connection - _at.cmd_start("AT+QCFGEXT=\"nipd\",1"); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); - - nsapi_size_or_error_t ret = _at.get_last_error(); - - _at.unlock(); + nsapi_size_or_error_t ret = _at.at_cmd_discard("+QCFGEXT", "=\"nipd\",1"); if (ret == NSAPI_ERROR_OK) { _semaphore.try_acquire_for(NIDD_OPEN_URC_TIMEOUT); @@ -115,28 +98,21 @@ nsapi_error_t QUECTEL_BG96_CellularContext::activate_non_ip_context() 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) { + + if (_at.at_cmd_discard("+QIACT", "=", "%d", _cid) == 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(); + _at.at_cmd_discard("+QIDEACT", "=", "%d", _cid); } void QUECTEL_BG96_CellularContext::deactivate_non_ip_context() { // Close the NIDD connection - _at.cmd_start("AT+QCFGEXT=\"nipd\",0"); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.at_cmd_discard("+QCFGEXT", "=\"nipd\",0"); } void QUECTEL_BG96_CellularContext::urc_nidd() @@ -178,30 +154,16 @@ nsapi_error_t QUECTEL_BG96_CellularContext::setup_control_plane_opt() { _at.lock(); - _at.cmd_start("AT+QCFGEXT=\"pdp_type\","); - _at.write_int(NIDD_PDP_CONTEXT_ID); - _at.write_string("Non-IP"); - _at.write_string(_apn); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); - _at.cmd_start("AT+CFUN=0"); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); - _at.cmd_start("AT+CFUN=1"); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.at_cmd_discard("+QCFGEXT", "=\"pdp_type\",", "%d%s%s", NIDD_PDP_CONTEXT_ID, "Non-IP", _apn); + + _at.at_cmd_discard("+CFUN", "=0"); + + _at.at_cmd_discard("+CFUN", "=1"); // Configure Non-IP outgoing data type - 0 for no exception data - _at.cmd_start("AT+QCFGEXT=\"nipdcfg\",0,"); - _at.write_string(_apn); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + nsapi_error_t err = _at.at_cmd_discard("+QCFGEXT", "=\"nipdcfg\",0,", "%s", _apn); - if (_at.get_last_error() == NSAPI_ERROR_OK) { + if (err == NSAPI_ERROR_OK) { _cp_in_use = true; if (_nonip_req) { _pdp_type = NON_IP_PDP_TYPE; diff --git a/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularInformation.cpp b/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularInformation.cpp index c8f4319ce6..7102e0fcc8 100644 --- a/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularInformation.cpp +++ b/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularInformation.cpp @@ -29,13 +29,7 @@ QUECTEL_BG96_CellularInformation::~QUECTEL_BG96_CellularInformation() // According to BG96_AT_Commands_Manual_V2.0 nsapi_error_t QUECTEL_BG96_CellularInformation::get_iccid(char *buf, size_t buf_size) { - _at.lock(); - _at.cmd_start("AT+QCCID"); - _at.cmd_stop(); - _at.resp_start("+QCCID:"); - _at.read_string(buf, buf_size); - _at.resp_stop(); - return _at.unlock_return_error(); + return _at.at_cmd_str("+QCCID", "", buf, buf_size); } } /* namespace mbed */ 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 8bee825808..40a4bdfef8 100644 --- a/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularNetwork.cpp +++ b/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularNetwork.cpp @@ -35,37 +35,27 @@ nsapi_error_t QUECTEL_BG96_CellularNetwork::set_access_technology_impl(RadioAcce switch (opsAct) { case RAT_CATM1: - _at.cmd_start("AT+QCFG=\"nwscanseq\",020301"); - _at.cmd_stop_read_resp(); - _at.cmd_start("AT+QCFG=\"nwscanmode\",3,1"); - _at.cmd_stop_read_resp(); - _at.cmd_start("AT+QCFG=\"iotopmode\",0,1"); - _at.cmd_stop_read_resp(); + _at.at_cmd_discard("+QCFG", "=\"nwscanseq\",020301"); + _at.at_cmd_discard("+QCFG", "=\"nwscanmode\",3,1"); + _at.at_cmd_discard("+QCFG", "=\"iotopmode\",0,1"); break; case RAT_NB1: - _at.cmd_start("AT+QCFG=\"nwscanseq\",030201"); - _at.cmd_stop_read_resp(); - _at.cmd_start("AT+QCFG=\"nwscanmode\",3,1"); - _at.cmd_stop_read_resp(); - _at.cmd_start("AT+QCFG=\"iotopmode\",1,1"); - _at.cmd_stop_read_resp(); + _at.at_cmd_discard("+QCFG", "=\"nwscanseq\",030201"); + _at.at_cmd_discard("+QCFG", "=\"nwscanmode\",3,1"); + _at.at_cmd_discard("+QCFG", "=\"iotopmode\",1,1"); break; case RAT_GSM: case RAT_GSM_COMPACT: case RAT_UTRAN: case RAT_EGPRS: - _at.cmd_start("AT+QCFG=\"nwscanseq\",010203"); - _at.cmd_stop_read_resp(); - _at.cmd_start("AT+QCFG=\"nwscanmode\",1,1"); - _at.cmd_stop_read_resp(); + _at.at_cmd_discard("+QCFG", "=\"nwscanseq\",010203"); + _at.at_cmd_discard("+QCFG", "=\"nwscanmode\",1,1"); break; default: - _at.cmd_start("AT+QCFG=\"nwscanseq\",020301"); - _at.cmd_stop_read_resp(); - _at.cmd_start("AT+QCFG=\"nwscanmode\",0,1"); //auto mode - _at.cmd_stop_read_resp(); - _at.cmd_start("AT+QCFG=\"iotopmode\",2,1"); //auto mode - _at.cmd_stop_read_resp(); + _at.at_cmd_discard("+QCFG", "=\"nwscanseq\",020301"); + _at.at_cmd_discard("+QCFG", "=\"nwscanmode\",0,1"); + _at.at_cmd_discard("+QCFG", "=\"iotopmode\",2,1"); + _at.unlock(); _op_act = RAT_UNKNOWN; return NSAPI_ERROR_UNSUPPORTED; @@ -77,8 +67,7 @@ nsapi_error_t QUECTEL_BG96_CellularNetwork::set_access_technology_impl(RadioAcce void QUECTEL_BG96_CellularNetwork::get_context_state_command() { // read active contexts - _at.cmd_start("AT+QIACT?"); - _at.cmd_stop(); + _at.cmd_start_stop("+QIACT", "?"); _at.resp_start("+QIACT:"); } diff --git a/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularStack.cpp b/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularStack.cpp index 7ad3892e22..1fdc2b408b 100755 --- a/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularStack.cpp +++ b/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularStack.cpp @@ -59,15 +59,8 @@ nsapi_error_t QUECTEL_BG96_CellularStack::socket_connect(nsapi_socket_t handle, _at.lock(); if (socket->proto == NSAPI_TCP) { - _at.cmd_start("AT+QIOPEN="); - _at.write_int(_cid); - _at.write_int(request_connect_id); - _at.write_string("TCP"); - _at.write_string(address.get_ip_address()); - _at.write_int(address.get_port()); - _at.write_int(socket->localAddress.get_port()); - _at.write_int(0); - _at.cmd_stop(); + _at.at_cmd_discard("+QIOPEN", "=", "%d%d%s%s%d%d%d", _cid, request_connect_id, "TCP", + address.get_ip_address(), address.get_port(), socket->localAddress.get_port(), 0); handle_open_socket_response(modem_connect_id, err); @@ -77,21 +70,10 @@ nsapi_error_t QUECTEL_BG96_CellularStack::socket_connect(nsapi_socket_t handle, _at.unlock(); return NSAPI_ERROR_PARAMETER; } - _at.cmd_start("AT+QICLOSE="); - _at.write_int(modem_connect_id); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.at_cmd_discard("+QICLOSE", "=", "%d", modem_connect_id); - _at.cmd_start("AT+QIOPEN="); - _at.write_int(_cid); - _at.write_int(request_connect_id); - _at.write_string("TCP"); - _at.write_string(address.get_ip_address()); - _at.write_int(address.get_port()); - _at.write_int(socket->localAddress.get_port()); - _at.write_int(0); - _at.cmd_stop(); + _at.at_cmd_discard("+QIOPEN", "=", "%d%d%s%s%d%d%d", _cid, request_connect_id, "TCP", + address.get_ip_address(), address.get_port(), socket->localAddress.get_port(), 0); handle_open_socket_response(modem_connect_id, err); } @@ -99,11 +81,7 @@ nsapi_error_t QUECTEL_BG96_CellularStack::socket_connect(nsapi_socket_t handle, // If opened successfully BUT not requested one, close it if (!err && (modem_connect_id != request_connect_id)) { - _at.cmd_start("AT+QICLOSE="); - _at.write_int(modem_connect_id); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); + _at.at_cmd_discard("+QICLOSE", "=", "%d", modem_connect_id); } nsapi_error_t ret_val = _at.get_last_error(); @@ -162,19 +140,15 @@ bool QUECTEL_BG96_CellularStack::is_protocol_supported(nsapi_protocol_t protocol nsapi_error_t QUECTEL_BG96_CellularStack::socket_close_impl(int sock_id) { _at.set_at_timeout(BG96_CLOSE_SOCKET_TIMEOUT); - _at.cmd_start("AT+QICLOSE="); - _at.write_int(sock_id); - _at.cmd_stop_read_resp(); + nsapi_error_t err = _at.at_cmd_discard("+QICLOSE", "=", "%d", sock_id); _at.restore_at_timeout(); - return _at.get_last_error(); + return err; } void QUECTEL_BG96_CellularStack::handle_open_socket_response(int &modem_connect_id, int &err) { // OK - _at.resp_start(); - _at.resp_stop(); // QIOPEN -> should be handled as URC? _at.set_at_timeout(BG96_CREATE_SOCKET_TIMEOUT); _at.resp_start("+QIOPEN:"); @@ -195,19 +169,9 @@ nsapi_error_t QUECTEL_BG96_CellularStack::create_socket_impl(CellularSocket *soc MBED_ASSERT(request_connect_id != -1); if (socket->proto == NSAPI_UDP && !socket->connected) { - _at.cmd_start("AT+QIOPEN="); - _at.write_int(_cid); - _at.write_int(request_connect_id); - _at.write_string("UDP SERVICE"); - if (_stack_type == IPV4_STACK) { - _at.write_string("127.0.0.1"); - } else if (_stack_type == IPV6_STACK || _stack_type == IPV4V6_STACK) { - _at.write_string("0:0:0:0:0:0:0:1"); - } - _at.write_int(remote_port); - _at.write_int(socket->localAddress.get_port()); - _at.write_int(0); - _at.cmd_stop(); + _at.at_cmd_discard("+QIOPEN", "=", "%d%d%s%s%d%d%d", _cid, request_connect_id, "UDP SERVICE", + (_stack_type == IPV4_STACK) ? "127.0.0.1" : "0:0:0:0:0:0:0:1", + remote_port, socket->localAddress.get_port(), 0); handle_open_socket_response(modem_connect_id, err); @@ -218,31 +182,15 @@ nsapi_error_t QUECTEL_BG96_CellularStack::create_socket_impl(CellularSocket *soc } socket_close_impl(modem_connect_id); - _at.cmd_start("AT+QIOPEN="); - _at.write_int(_cid); - _at.write_int(request_connect_id); - _at.write_string("UDP SERVICE"); - - if (_stack_type == IPV4_STACK) { - _at.write_string("127.0.0.1"); - } else if (_stack_type == IPV6_STACK || _stack_type == IPV4V6_STACK) { - _at.write_string("0:0:0:0:0:0:0:1"); - } - _at.write_int(remote_port); - _at.write_int(socket->localAddress.get_port()); - _at.write_int(0); - _at.cmd_stop(); + _at.at_cmd_discard("+QIOPEN", "=", "%d%d%s%s%d%d%d", _cid, request_connect_id, "UDP SERVICE", + (_stack_type == IPV4_STACK) ? "127.0.0.1" : "0:0:0:0:0:0:0:1", + remote_port, socket->localAddress.get_port(), 0); handle_open_socket_response(modem_connect_id, err); } } else if (socket->proto == NSAPI_UDP && socket->connected) { - _at.cmd_start("AT+QIOPEN="); - _at.write_int(_cid); - _at.write_int(request_connect_id); - _at.write_string("UDP"); - _at.write_string(socket->remoteAddress.get_ip_address()); - _at.write_int(socket->remoteAddress.get_port()); - _at.cmd_stop(); + _at.at_cmd_discard("+QIOPEN", "=", "%d%d%s%s%d", _cid, request_connect_id, "UDP", + socket->remoteAddress.get_ip_address(), socket->remoteAddress.get_port()); handle_open_socket_response(modem_connect_id, err); @@ -253,13 +201,8 @@ nsapi_error_t QUECTEL_BG96_CellularStack::create_socket_impl(CellularSocket *soc } socket_close_impl(modem_connect_id); - _at.cmd_start("AT+QIOPEN="); - _at.write_int(_cid); - _at.write_int(request_connect_id); - _at.write_string("UDP"); - _at.write_string(socket->remoteAddress.get_ip_address()); - _at.write_int(socket->remoteAddress.get_port()); - _at.cmd_stop(); + _at.at_cmd_discard("+QIOPEN", "=", "%d%d%s%s%d", _cid, request_connect_id, "UDP", + socket->remoteAddress.get_ip_address(), socket->remoteAddress.get_port()); handle_open_socket_response(modem_connect_id, err); } @@ -291,24 +234,15 @@ nsapi_size_or_error_t QUECTEL_BG96_CellularStack::socket_sendto_impl(CellularSoc int sent_len_after = 0; // Get the sent count before sending - _at.cmd_start("AT+QISEND="); - _at.write_int(socket->id); - _at.write_int(0); - _at.cmd_stop(); - - _at.resp_start("+QISEND:"); - sent_len_before = _at.read_int(); - _at.resp_stop(); + _at.at_cmd_int("+QISEND", "=", sent_len_before, "%d%d", socket->id, 0); // Send - _at.cmd_start("AT+QISEND="); - _at.write_int(socket->id); - _at.write_int(size); if (socket->proto == NSAPI_UDP) { - _at.write_string(address.get_ip_address()); - _at.write_int(address.get_port()); + _at.cmd_start_stop("+QISEND", "=", "%d%d%s%d", socket->id, size, + address.get_ip_address(), address.get_port()); + } else { + _at.cmd_start_stop("+QISEND", "=", "%d%d", socket->id, size); } - _at.cmd_stop(); _at.resp_start(">"); _at.write_bytes((uint8_t *)data, size); @@ -317,21 +251,15 @@ nsapi_size_or_error_t QUECTEL_BG96_CellularStack::socket_sendto_impl(CellularSoc _at.resp_stop(); // Get the sent count after sending - _at.cmd_start("AT+QISEND="); - _at.write_int(socket->id); - _at.write_int(0); - _at.cmd_stop(); - _at.resp_start("+QISEND:"); - sent_len_after = _at.read_int(); - _at.resp_stop(); + nsapi_size_or_error_t err = _at.at_cmd_int("+QISEND", "=", sent_len_after, "%d%d", socket->id, 0); - if (_at.get_last_error() == NSAPI_ERROR_OK) { + if (err == NSAPI_ERROR_OK) { sent_len = sent_len_after - sent_len_before; return sent_len; } - return _at.get_last_error(); + return err; } nsapi_size_or_error_t QUECTEL_BG96_CellularStack::socket_recvfrom_impl(CellularSocket *socket, SocketAddress *address, @@ -341,14 +269,13 @@ nsapi_size_or_error_t QUECTEL_BG96_CellularStack::socket_recvfrom_impl(CellularS int port; char ip_address[NSAPI_IP_SIZE + 1]; - _at.cmd_start("AT+QIRD="); - _at.write_int(socket->id); if (socket->proto == NSAPI_TCP) { // do not read more than max size size = size > BG96_MAX_RECV_SIZE ? BG96_MAX_RECV_SIZE : size; - _at.write_int(size); + _at.cmd_start_stop("+QIRD", "=", "%d%d", socket->id, size); + } else { + _at.cmd_start_stop("+QIRD", "=", "%d", socket->id); } - _at.cmd_stop(); _at.resp_start("+QIRD:"); recv_len = _at.read_int(); diff --git a/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_ControlPlane_netif.cpp b/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_ControlPlane_netif.cpp index 5d2036c76a..f988530935 100644 --- a/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_ControlPlane_netif.cpp +++ b/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_ControlPlane_netif.cpp @@ -7,18 +7,7 @@ QUECTEL_BG96_ControlPlane_netif::QUECTEL_BG96_ControlPlane_netif(ATHandler &at, nsapi_size_or_error_t QUECTEL_BG96_ControlPlane_netif::send(const void *data, nsapi_size_t size) { - _at.lock(); - - _at.cmd_start("AT+QCFGEXT=\"nipds\",0,"); - _at.write_string((char *)data); - _at.write_int(size); - _at.cmd_stop(); - _at.resp_start(); - _at.resp_stop(); - - nsapi_error_t err = _at.get_last_error(); - - _at.unlock(); + nsapi_size_or_error_t err = _at.at_cmd_discard("+QCFGEXT", "=\"nipds\",0,", "%s%d", data, size); if (err == NSAPI_ERROR_OK) { return size;