Skip to content

Cellular: send disconnect to correct ctx #10402

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 29, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions UNITTESTS/stubs/ATHandler_stub.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,11 @@ void ATHandler::set_file_handle(FileHandle *fh)

void ATHandler::set_urc_handler(const char *urc, mbed::Callback<void()> cb)
{
if (!cb) {
remove_urc_handler(urc);
return;
}

if (ATHandler_stub::urc_amount < kATHandler_urc_table_max_size) {
ATHandler_stub::callback[ATHandler_stub::urc_amount] = cb;
if (urc) {
Expand All @@ -176,6 +181,20 @@ void ATHandler::set_urc_handler(const char *urc, mbed::Callback<void()> cb)

void ATHandler::remove_urc_handler(const char *prefix)
{
bool found_urc = false;
for (int i = 0; i < ATHandler_stub::urc_amount; i++) {
if (found_urc && i < 0) {
ATHandler_stub::urc_string_table[i - 1] = ATHandler_stub::urc_string_table[i];
ATHandler_stub::urc_string_table[i] = 0;
} else if (ATHandler_stub::urc_string_table[i] && strcmp(prefix, ATHandler_stub::urc_string_table[i]) == 0) {
delete [] ATHandler_stub::urc_string_table[i];
ATHandler_stub::urc_string_table[i] = 0;
found_urc = true;
}
}
if (found_urc) {
ATHandler_stub::urc_amount--;
}
}

nsapi_error_t ATHandler::get_last_error() const
Expand Down
5 changes: 0 additions & 5 deletions UNITTESTS/stubs/AT_CellularNetwork_stub.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,6 @@ nsapi_error_t AT_CellularNetwork::detach()
return NSAPI_ERROR_OK;
}

void AT_CellularNetwork::urc_no_carrier()
{

}

nsapi_error_t AT_CellularNetwork::set_access_technology_impl(RadioAccessTechnology opsAct)
{
return NSAPI_ERROR_OK;
Expand Down
5 changes: 5 additions & 0 deletions UNITTESTS/stubs/CellularContext_stub.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ CellularDevice *CellularContext::get_device() const
return _device;
}

int CellularContext::get_cid() const
{
return _cid;
}

void CellularContext::do_connect_with_retry()
{
do_connect();
Expand Down
6 changes: 6 additions & 0 deletions features/cellular/framework/API/CellularContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,12 @@ class CellularContext : public CellularInterface {
*/
virtual ControlPlane_netif *get_cp_netif() = 0;

/** Get the pdp context id associated with this context.
*
* @return cid
*/
int get_cid() const;

protected: // Device specific implementations might need these so protected
enum ContextOperation {
OP_INVALID = -1,
Expand Down
2 changes: 1 addition & 1 deletion features/cellular/framework/AT/ATHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ class ATHandler {

/** Set callback function for URC
*
* @param prefix URC text to look for, e.g. "+CMTI:"
* @param prefix URC text to look for, e.g. "+CMTI:". Maximum length is BUFF_SIZE.
* @param callback function to call on prefix, or 0 to remove callback
*/
void set_urc_handler(const char *prefix, Callback<void()> callback);
Expand Down
12 changes: 6 additions & 6 deletions features/cellular/framework/AT/AT_CellularBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,18 +67,18 @@ class AT_CellularBase {
*/
static void set_cellular_properties(const intptr_t *property_array);

protected:

static const intptr_t *_property_array;

ATHandler &_at;

/** Get value for the given key.
*
* @param key key for value to be fetched
* @return property value for the given key. Value type is defined in enum CellularProperty
*/
static intptr_t get_property(CellularProperty key);

protected:

static const intptr_t *_property_array;

ATHandler &_at;
};

} // namespace mbed
Expand Down
49 changes: 26 additions & 23 deletions features/cellular/framework/AT/AT_CellularContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
// Timeout to wait for URC indicating ciot optimization support from network
#define CP_OPT_NW_REPLY_TIMEOUT 3000 // 3 seconds


#if NSAPI_PPP_AVAILABLE
#define AT_SYNC_TIMEOUT 1000 // 1 second timeout
#include "nsapi_ppp.h"
Expand Down Expand Up @@ -591,8 +590,6 @@ void AT_CellularContext::do_connect()
_at.unlock();
if (_cb_data.error != NSAPI_ERROR_OK) {
_is_connected = false;
} else {
_is_context_activated = true;
}
}
#else
Expand Down Expand Up @@ -646,21 +643,20 @@ nsapi_error_t AT_CellularContext::open_data_channel()
void AT_CellularContext::ppp_status_cb(nsapi_event_t ev, intptr_t ptr)
{
tr_debug("ppp_status_cb: event %d, ptr %d", ev, ptr);

if (ev == NSAPI_EVENT_CONNECTION_STATUS_CHANGE && ptr == NSAPI_STATUS_GLOBAL_UP) {
_is_connected = true;
} else {
_is_connected = false;
}

_connect_status = (nsapi_connection_status_t)ptr;

// catch all NSAPI_STATUS_DISCONNECTED events but send to device only when we did not ask for disconnect.
if (ev == NSAPI_EVENT_CONNECTION_STATUS_CHANGE && ptr == NSAPI_STATUS_DISCONNECTED) {
if (_is_connected) {
ppp_disconnected();
_device->cellular_callback(ev, ptr, this);
// catch all NSAPI_STATUS_DISCONNECTED events but send to device only when we did not ask for disconnect.
if (ev == NSAPI_EVENT_CONNECTION_STATUS_CHANGE && ptr == NSAPI_STATUS_DISCONNECTED) {
if (_is_connected) { // set to false in disconnect() before calling nsapi_ppp_disconnect()
_is_connected = false;
ppp_disconnected();
_device->cellular_callback(ev, ptr, this);
}
return; // return here so if we were not in connected state we don't send NSAPI_STATUS_DISCONNECTED event
}
return;
_is_connected = false;
}

// call device's callback, it will broadcast this to here (cellular_callback)
Expand Down Expand Up @@ -714,11 +710,14 @@ nsapi_error_t AT_CellularContext::disconnect()
deactivate_ip_context();
}
}

// don't call multiple times disconnect if we already got that event from network urc or ppp
if (_connect_status != NSAPI_STATUS_DISCONNECTED) {
_device->cellular_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_DISCONNECTED, this);
}
_is_context_active = false;
_connect_status = NSAPI_STATUS_DISCONNECTED;

// call device's callback, it will broadcast this to here (cellular_callback)
_device->cellular_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_DISCONNECTED, this);

if (_new_context_set) {
delete_current_context();
Expand Down Expand Up @@ -770,6 +769,8 @@ void AT_CellularContext::check_and_deactivate_context()
_at.write_int(_cid);
_at.cmd_stop_read_resp();
}

_at.restore_at_timeout();
}

nsapi_error_t AT_CellularContext::get_apn_backoff_timer(int &backoff_timer)
Expand Down Expand Up @@ -993,7 +994,7 @@ void AT_CellularContext::cellular_callback(nsapi_event_t ev, intptr_t ptr)
if (st == CellularAttachNetwork && _current_op == OP_CONNECT && _cb_data.error == NSAPI_ERROR_OK &&
data->status_data == CellularNetwork::Attached) {
_current_op = OP_INVALID;
// forward to application
// forward all Cellular specific events to application
if (_status_cb) {
_status_cb(ev, ptr);
}
Expand All @@ -1002,14 +1003,19 @@ void AT_CellularContext::cellular_callback(nsapi_event_t ev, intptr_t ptr)
return;
}
}

// forward all Cellular specific events to application
if (_status_cb) {
_status_cb(ev, ptr);
}
} else {
#if NSAPI_PPP_AVAILABLE
if (_is_blocking) {
if (ev == NSAPI_EVENT_CONNECTION_STATUS_CHANGE && ptr == NSAPI_STATUS_GLOBAL_UP) {
tr_info("CellularContext IP %s", get_ip_address());
_cb_data.error = NSAPI_ERROR_OK;
} else if (ev == NSAPI_EVENT_CONNECTION_STATUS_CHANGE && ptr == NSAPI_STATUS_DISCONNECTED) {
tr_info("PPP disconnected");
tr_info("cellular_callback: PPP mode and NSAPI_STATUS_DISCONNECTED");
_cb_data.error = NSAPI_ERROR_NO_CONNECTION;
}
}
Expand All @@ -1020,11 +1026,8 @@ void AT_CellularContext::cellular_callback(nsapi_event_t ev, intptr_t ptr)
}
#endif // MBED_CONF_MBED_TRACE_ENABLE
#endif // NSAPI_PPP_AVAILABLE
}

// forward to application
if (_status_cb) {
_status_cb(ev, ptr);
// forward status change events to application, call_network_cb will make sure that only changed event are forwarded
call_network_cb((nsapi_connection_status_t)ptr);
}
}

Expand Down
1 change: 0 additions & 1 deletion features/cellular/framework/AT/AT_CellularContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,6 @@ class AT_CellularContext : public CellularContext, public AT_CellularBase {
bool _cp_req;
// flag indicating if Non-IP context was requested to be setup
bool _nonip_req;

// tells if CCIOTOPTI received green from network for CP optimization use
bool _cp_in_use;
};
Expand Down
65 changes: 65 additions & 0 deletions features/cellular/framework/AT/AT_CellularDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "UARTSerial.h"
#endif // #if DEVICE_SERIAL
#include "FileHandle.h"
#include <ctype.h>

using namespace mbed_cellular_util;
using namespace events;
Expand All @@ -43,10 +44,24 @@ AT_CellularDevice::AT_CellularDevice(FileHandle *fh) : CellularDevice(fh), _netw
MBED_ASSERT(fh);
_at = get_at_handler(fh);
MBED_ASSERT(_at);

if (AT_CellularBase::get_property(AT_CellularBase::PROPERTY_AT_CGEREP)) {
_at->set_urc_handler("+CGEV: NW DEACT", callback(this, &AT_CellularDevice::urc_nw_deact));
_at->set_urc_handler("+CGEV: ME DEACT", callback(this, &AT_CellularDevice::urc_nw_deact));
_at->set_urc_handler("+CGEV: NW PDN D", callback(this, &AT_CellularDevice::urc_pdn_deact));
_at->set_urc_handler("+CGEV: ME PDN D", callback(this, &AT_CellularDevice::urc_pdn_deact));
}
}

AT_CellularDevice::~AT_CellularDevice()
{
if (AT_CellularBase::get_property(AT_CellularBase::PROPERTY_AT_CGEREP)) {
_at->set_urc_handler("+CGEV: NW DEACT", 0);
_at->set_urc_handler("+CGEV: ME DEACT", 0);
_at->set_urc_handler("+CGEV: NW PDN D", 0);
_at->set_urc_handler("+CGEV: ME PDN D", 0);
}

// make sure that all is deleted even if somewhere close was not called and reference counting is messed up.
_network_ref_count = 1;
_sms_ref_count = 1;
Expand All @@ -69,6 +84,56 @@ AT_CellularDevice::~AT_CellularDevice()
release_at_handler(_at);
}

void AT_CellularDevice::urc_nw_deact()
{
// The network has forced a context deactivation
char buf[10];
_at->read_string(buf, 10);
int cid;
if (isalpha(buf[0])) {
// this is +CGEV: NW DEACT <PDP_type>, <PDP_addr>, [<cid>]
// or +CGEV: ME DEACT <PDP_type>, <PDP_addr>, [<cid>]
_at->skip_param(); // skip <PDP_addr>
cid = _at->read_int();
} else {
// this is +CGEV: NW DEACT <p_cid>, <cid>, <event_type>[,<WLAN_Offload>]
// or +CGEV: ME DEACT <p_cid>, <cid>, <event_type
cid = _at->read_int();
}
send_disconnect_to_context(cid);
}

void AT_CellularDevice::urc_pdn_deact()
{
// The network has deactivated a context
// The mobile termination has deactivated a context.
// +CGEV: NW PDN DEACT <cid>[,<WLAN_Offload>]
// +CGEV: ME PDN DEACT <cid>
_at->set_delimiter(' ');
_at->skip_param();
_at->set_delimiter(',');

int cid = _at->read_int();
send_disconnect_to_context(cid);
}

void AT_CellularDevice::send_disconnect_to_context(int cid)
{
tr_debug("send_disconnect_to_context, cid: %d", cid);
AT_CellularContext *curr = _context_list;
while (curr) {
if (cid >= 0) {
if (curr->get_cid() == cid) {
CellularDevice::cellular_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_DISCONNECTED, curr);
break;
}
} else {
CellularDevice::cellular_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_DISCONNECTED);
}
curr = (AT_CellularContext *)curr->_next;
}
}

nsapi_error_t AT_CellularDevice::hard_power_on()
{
return NSAPI_ERROR_OK;
Expand Down
5 changes: 5 additions & 0 deletions features/cellular/framework/AT/AT_CellularDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,11 @@ class AT_CellularDevice : public CellularDevice {
int _default_timeout;
bool _modem_debug_on;
ATHandler *_at;

private:
void urc_nw_deact();
void urc_pdn_deact();
void send_disconnect_to_context(int cid);
};

} // namespace mbed
Expand Down
Loading