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 9fc556e9d6..a1488e5be5 100644 --- a/UNITTESTS/features/cellular/framework/AT/at_cellularcontext/at_cellularcontexttest.cpp +++ b/UNITTESTS/features/cellular/framework/AT/at_cellularcontext/at_cellularcontexttest.cpp @@ -603,15 +603,22 @@ TEST_F(TestAT_CellularContext, connect_disconnect_async) ASSERT_EQ(network_cb_count, 5); ASSERT_EQ(ctx1.connect(), NSAPI_ERROR_IS_CONNECTED); EXPECT_TRUE(ctx1.is_connected() == true); + ASSERT_EQ(ctx1.disconnect(), NSAPI_ERROR_NO_MEMORY); + EXPECT_TRUE(ctx1.is_connected() == true); + + struct equeue_event ptr; + equeue_stub.void_ptr = &ptr; + equeue_stub.call_cb_immediately = true; ASSERT_EQ(ctx1.disconnect(), NSAPI_ERROR_OK); EXPECT_TRUE(ctx1.is_connected() == false); // sdet CellularDevice_stub::connect_counter = 0 so device is already attached and will return NSAPI_ERROR_ALREADY to context when calling connect + equeue_stub.void_ptr = &ptr; + equeue_stub.call_cb_immediately = false; CellularDevice_stub::connect_counter = 0; // queue can't allocate so return NSAPI_ERROR_NO_MEMORY ASSERT_EQ(ctx1.connect(), NSAPI_ERROR_NO_MEMORY); - struct equeue_event ptr; equeue_stub.void_ptr = &ptr; equeue_stub.call_cb_immediately = true; ASSERT_EQ(ctx1.connect(), NSAPI_ERROR_OK); diff --git a/features/cellular/framework/AT/AT_CellularContext.cpp b/features/cellular/framework/AT/AT_CellularContext.cpp index 8e235f1bc7..d6e0c3b972 100644 --- a/features/cellular/framework/AT/AT_CellularContext.cpp +++ b/features/cellular/framework/AT/AT_CellularContext.cpp @@ -59,6 +59,7 @@ AT_CellularContext::~AT_CellularContext() { tr_info("Delete CellularContext with apn: [%s] (%p)", _apn ? _apn : "", this); + _is_blocking = true; (void)disconnect(); if (_nw) { @@ -659,15 +660,14 @@ void AT_CellularContext::ppp_disconnected() #endif //#if NSAPI_PPP_AVAILABLE -nsapi_error_t AT_CellularContext::disconnect() +void AT_CellularContext::do_disconnect() { - tr_info("CellularContext disconnect()"); if (!_nw || !_is_connected) { if (_new_context_set) { delete_current_context(); } _cid = -1; - return NSAPI_ERROR_NO_CONNECTION; + _cb_data.error = NSAPI_ERROR_NO_CONNECTION; } // set false here so callbacks know that we are not connected and so should not send DISCONNECTED @@ -703,8 +703,22 @@ nsapi_error_t AT_CellularContext::disconnect() delete_current_context(); } _cid = -1; + _cb_data.error = _at.unlock_return_error(); +} - return _at.unlock_return_error(); +nsapi_error_t AT_CellularContext::disconnect() +{ + tr_info("CellularContext disconnect()"); + if (_is_blocking) { + do_disconnect(); + return _cb_data.error; + } else { + int event_id = _device->get_queue()->call_in(0, this, &AT_CellularContext::do_disconnect); + if (event_id == 0) { + return NSAPI_ERROR_NO_MEMORY; + } + return NSAPI_ERROR_OK; + } } void AT_CellularContext::deactivate_ip_context() diff --git a/features/cellular/framework/AT/AT_CellularContext.h b/features/cellular/framework/AT/AT_CellularContext.h index f2a7becb21..2831a3ff7b 100644 --- a/features/cellular/framework/AT/AT_CellularContext.h +++ b/features/cellular/framework/AT/AT_CellularContext.h @@ -118,6 +118,7 @@ private: AT_CellularBase::CellularProperty pdp_type_t_to_cellular_property(pdp_type_t pdp_type); void ciot_opt_cb(mbed::CellularNetwork::CIoT_Supported_Opt ciot_opt); virtual void do_connect_with_retry(); + void do_disconnect(); private: bool _is_connected; ContextOperation _current_op;