Skip to content

Commit 1ce073a

Browse files
authored
Merge pull request #10402 from jarvte/disconnect_per_context
Cellular: send disconnect to correct ctx
2 parents f28b82b + 9d67a8b commit 1ce073a

14 files changed

+155
-80
lines changed

UNITTESTS/stubs/ATHandler_stub.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,11 @@ void ATHandler::set_file_handle(FileHandle *fh)
156156

157157
void ATHandler::set_urc_handler(const char *urc, mbed::Callback<void()> cb)
158158
{
159+
if (!cb) {
160+
remove_urc_handler(urc);
161+
return;
162+
}
163+
159164
if (ATHandler_stub::urc_amount < kATHandler_urc_table_max_size) {
160165
ATHandler_stub::callback[ATHandler_stub::urc_amount] = cb;
161166
if (urc) {
@@ -176,6 +181,20 @@ void ATHandler::set_urc_handler(const char *urc, mbed::Callback<void()> cb)
176181

177182
void ATHandler::remove_urc_handler(const char *prefix)
178183
{
184+
bool found_urc = false;
185+
for (int i = 0; i < ATHandler_stub::urc_amount; i++) {
186+
if (found_urc && i < 0) {
187+
ATHandler_stub::urc_string_table[i - 1] = ATHandler_stub::urc_string_table[i];
188+
ATHandler_stub::urc_string_table[i] = 0;
189+
} else if (ATHandler_stub::urc_string_table[i] && strcmp(prefix, ATHandler_stub::urc_string_table[i]) == 0) {
190+
delete [] ATHandler_stub::urc_string_table[i];
191+
ATHandler_stub::urc_string_table[i] = 0;
192+
found_urc = true;
193+
}
194+
}
195+
if (found_urc) {
196+
ATHandler_stub::urc_amount--;
197+
}
179198
}
180199

181200
nsapi_error_t ATHandler::get_last_error() const

UNITTESTS/stubs/AT_CellularNetwork_stub.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,6 @@ nsapi_error_t AT_CellularNetwork::detach()
9595
return NSAPI_ERROR_OK;
9696
}
9797

98-
void AT_CellularNetwork::urc_no_carrier()
99-
{
100-
101-
}
102-
10398
nsapi_error_t AT_CellularNetwork::set_access_technology_impl(RadioAccessTechnology opsAct)
10499
{
105100
return NSAPI_ERROR_OK;

UNITTESTS/stubs/CellularContext_stub.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ CellularDevice *CellularContext::get_device() const
2929
return _device;
3030
}
3131

32+
int CellularContext::get_cid() const
33+
{
34+
return _cid;
35+
}
36+
3237
void CellularContext::do_connect_with_retry()
3338
{
3439
do_connect();

features/cellular/framework/API/CellularContext.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,12 @@ class CellularContext : public CellularInterface {
282282
*/
283283
virtual ControlPlane_netif *get_cp_netif() = 0;
284284

285+
/** Get the pdp context id associated with this context.
286+
*
287+
* @return cid
288+
*/
289+
int get_cid() const;
290+
285291
protected: // Device specific implementations might need these so protected
286292
enum ContextOperation {
287293
OP_INVALID = -1,

features/cellular/framework/AT/ATHandler.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ class ATHandler {
121121

122122
/** Set callback function for URC
123123
*
124-
* @param prefix URC text to look for, e.g. "+CMTI:"
124+
* @param prefix URC text to look for, e.g. "+CMTI:". Maximum length is BUFF_SIZE.
125125
* @param callback function to call on prefix, or 0 to remove callback
126126
*/
127127
void set_urc_handler(const char *prefix, Callback<void()> callback);

features/cellular/framework/AT/AT_CellularBase.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,18 +67,18 @@ class AT_CellularBase {
6767
*/
6868
static void set_cellular_properties(const intptr_t *property_array);
6969

70-
protected:
71-
72-
static const intptr_t *_property_array;
73-
74-
ATHandler &_at;
75-
7670
/** Get value for the given key.
7771
*
7872
* @param key key for value to be fetched
7973
* @return property value for the given key. Value type is defined in enum CellularProperty
8074
*/
8175
static intptr_t get_property(CellularProperty key);
76+
77+
protected:
78+
79+
static const intptr_t *_property_array;
80+
81+
ATHandler &_at;
8282
};
8383

8484
} // namespace mbed

features/cellular/framework/AT/AT_CellularContext.cpp

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
// Timeout to wait for URC indicating ciot optimization support from network
3232
#define CP_OPT_NW_REPLY_TIMEOUT 3000 // 3 seconds
3333

34-
3534
#if NSAPI_PPP_AVAILABLE
3635
#define AT_SYNC_TIMEOUT 1000 // 1 second timeout
3736
#include "nsapi_ppp.h"
@@ -591,8 +590,6 @@ void AT_CellularContext::do_connect()
591590
_at.unlock();
592591
if (_cb_data.error != NSAPI_ERROR_OK) {
593592
_is_connected = false;
594-
} else {
595-
_is_context_activated = true;
596593
}
597594
}
598595
#else
@@ -646,21 +643,20 @@ nsapi_error_t AT_CellularContext::open_data_channel()
646643
void AT_CellularContext::ppp_status_cb(nsapi_event_t ev, intptr_t ptr)
647644
{
648645
tr_debug("ppp_status_cb: event %d, ptr %d", ev, ptr);
646+
649647
if (ev == NSAPI_EVENT_CONNECTION_STATUS_CHANGE && ptr == NSAPI_STATUS_GLOBAL_UP) {
650648
_is_connected = true;
651649
} else {
652-
_is_connected = false;
653-
}
654-
655-
_connect_status = (nsapi_connection_status_t)ptr;
656-
657-
// catch all NSAPI_STATUS_DISCONNECTED events but send to device only when we did not ask for disconnect.
658-
if (ev == NSAPI_EVENT_CONNECTION_STATUS_CHANGE && ptr == NSAPI_STATUS_DISCONNECTED) {
659-
if (_is_connected) {
660-
ppp_disconnected();
661-
_device->cellular_callback(ev, ptr, this);
650+
// catch all NSAPI_STATUS_DISCONNECTED events but send to device only when we did not ask for disconnect.
651+
if (ev == NSAPI_EVENT_CONNECTION_STATUS_CHANGE && ptr == NSAPI_STATUS_DISCONNECTED) {
652+
if (_is_connected) { // set to false in disconnect() before calling nsapi_ppp_disconnect()
653+
_is_connected = false;
654+
ppp_disconnected();
655+
_device->cellular_callback(ev, ptr, this);
656+
}
657+
return; // return here so if we were not in connected state we don't send NSAPI_STATUS_DISCONNECTED event
662658
}
663-
return;
659+
_is_connected = false;
664660
}
665661

666662
// call device's callback, it will broadcast this to here (cellular_callback)
@@ -714,11 +710,14 @@ nsapi_error_t AT_CellularContext::disconnect()
714710
deactivate_ip_context();
715711
}
716712
}
713+
714+
// don't call multiple times disconnect if we already got that event from network urc or ppp
715+
if (_connect_status != NSAPI_STATUS_DISCONNECTED) {
716+
_device->cellular_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_DISCONNECTED, this);
717+
}
717718
_is_context_active = false;
718719
_connect_status = NSAPI_STATUS_DISCONNECTED;
719720

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

723722
if (_new_context_set) {
724723
delete_current_context();
@@ -770,6 +769,8 @@ void AT_CellularContext::check_and_deactivate_context()
770769
_at.write_int(_cid);
771770
_at.cmd_stop_read_resp();
772771
}
772+
773+
_at.restore_at_timeout();
773774
}
774775

775776
nsapi_error_t AT_CellularContext::get_apn_backoff_timer(int &backoff_timer)
@@ -993,7 +994,7 @@ void AT_CellularContext::cellular_callback(nsapi_event_t ev, intptr_t ptr)
993994
if (st == CellularAttachNetwork && _current_op == OP_CONNECT && _cb_data.error == NSAPI_ERROR_OK &&
994995
data->status_data == CellularNetwork::Attached) {
995996
_current_op = OP_INVALID;
996-
// forward to application
997+
// forward all Cellular specific events to application
997998
if (_status_cb) {
998999
_status_cb(ev, ptr);
9991000
}
@@ -1002,14 +1003,19 @@ void AT_CellularContext::cellular_callback(nsapi_event_t ev, intptr_t ptr)
10021003
return;
10031004
}
10041005
}
1006+
1007+
// forward all Cellular specific events to application
1008+
if (_status_cb) {
1009+
_status_cb(ev, ptr);
1010+
}
10051011
} else {
10061012
#if NSAPI_PPP_AVAILABLE
10071013
if (_is_blocking) {
10081014
if (ev == NSAPI_EVENT_CONNECTION_STATUS_CHANGE && ptr == NSAPI_STATUS_GLOBAL_UP) {
10091015
tr_info("CellularContext IP %s", get_ip_address());
10101016
_cb_data.error = NSAPI_ERROR_OK;
10111017
} else if (ev == NSAPI_EVENT_CONNECTION_STATUS_CHANGE && ptr == NSAPI_STATUS_DISCONNECTED) {
1012-
tr_info("PPP disconnected");
1018+
tr_info("cellular_callback: PPP mode and NSAPI_STATUS_DISCONNECTED");
10131019
_cb_data.error = NSAPI_ERROR_NO_CONNECTION;
10141020
}
10151021
}
@@ -1020,11 +1026,8 @@ void AT_CellularContext::cellular_callback(nsapi_event_t ev, intptr_t ptr)
10201026
}
10211027
#endif // MBED_CONF_MBED_TRACE_ENABLE
10221028
#endif // NSAPI_PPP_AVAILABLE
1023-
}
1024-
1025-
// forward to application
1026-
if (_status_cb) {
1027-
_status_cb(ev, ptr);
1029+
// forward status change events to application, call_network_cb will make sure that only changed event are forwarded
1030+
call_network_cb((nsapi_connection_status_t)ptr);
10281031
}
10291032
}
10301033

features/cellular/framework/AT/AT_CellularContext.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,6 @@ class AT_CellularContext : public CellularContext, public AT_CellularBase {
131131
bool _cp_req;
132132
// flag indicating if Non-IP context was requested to be setup
133133
bool _nonip_req;
134-
135134
// tells if CCIOTOPTI received green from network for CP optimization use
136135
bool _cp_in_use;
137136
};

features/cellular/framework/AT/AT_CellularDevice.cpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "UARTSerial.h"
2929
#endif // #if DEVICE_SERIAL
3030
#include "FileHandle.h"
31+
#include <ctype.h>
3132

3233
using namespace mbed_cellular_util;
3334
using namespace events;
@@ -43,10 +44,24 @@ AT_CellularDevice::AT_CellularDevice(FileHandle *fh) : CellularDevice(fh), _netw
4344
MBED_ASSERT(fh);
4445
_at = get_at_handler(fh);
4546
MBED_ASSERT(_at);
47+
48+
if (AT_CellularBase::get_property(AT_CellularBase::PROPERTY_AT_CGEREP)) {
49+
_at->set_urc_handler("+CGEV: NW DEACT", callback(this, &AT_CellularDevice::urc_nw_deact));
50+
_at->set_urc_handler("+CGEV: ME DEACT", callback(this, &AT_CellularDevice::urc_nw_deact));
51+
_at->set_urc_handler("+CGEV: NW PDN D", callback(this, &AT_CellularDevice::urc_pdn_deact));
52+
_at->set_urc_handler("+CGEV: ME PDN D", callback(this, &AT_CellularDevice::urc_pdn_deact));
53+
}
4654
}
4755

4856
AT_CellularDevice::~AT_CellularDevice()
4957
{
58+
if (AT_CellularBase::get_property(AT_CellularBase::PROPERTY_AT_CGEREP)) {
59+
_at->set_urc_handler("+CGEV: NW DEACT", 0);
60+
_at->set_urc_handler("+CGEV: ME DEACT", 0);
61+
_at->set_urc_handler("+CGEV: NW PDN D", 0);
62+
_at->set_urc_handler("+CGEV: ME PDN D", 0);
63+
}
64+
5065
// make sure that all is deleted even if somewhere close was not called and reference counting is messed up.
5166
_network_ref_count = 1;
5267
_sms_ref_count = 1;
@@ -69,6 +84,56 @@ AT_CellularDevice::~AT_CellularDevice()
6984
release_at_handler(_at);
7085
}
7186

87+
void AT_CellularDevice::urc_nw_deact()
88+
{
89+
// The network has forced a context deactivation
90+
char buf[10];
91+
_at->read_string(buf, 10);
92+
int cid;
93+
if (isalpha(buf[0])) {
94+
// this is +CGEV: NW DEACT <PDP_type>, <PDP_addr>, [<cid>]
95+
// or +CGEV: ME DEACT <PDP_type>, <PDP_addr>, [<cid>]
96+
_at->skip_param(); // skip <PDP_addr>
97+
cid = _at->read_int();
98+
} else {
99+
// this is +CGEV: NW DEACT <p_cid>, <cid>, <event_type>[,<WLAN_Offload>]
100+
// or +CGEV: ME DEACT <p_cid>, <cid>, <event_type
101+
cid = _at->read_int();
102+
}
103+
send_disconnect_to_context(cid);
104+
}
105+
106+
void AT_CellularDevice::urc_pdn_deact()
107+
{
108+
// The network has deactivated a context
109+
// The mobile termination has deactivated a context.
110+
// +CGEV: NW PDN DEACT <cid>[,<WLAN_Offload>]
111+
// +CGEV: ME PDN DEACT <cid>
112+
_at->set_delimiter(' ');
113+
_at->skip_param();
114+
_at->set_delimiter(',');
115+
116+
int cid = _at->read_int();
117+
send_disconnect_to_context(cid);
118+
}
119+
120+
void AT_CellularDevice::send_disconnect_to_context(int cid)
121+
{
122+
tr_debug("send_disconnect_to_context, cid: %d", cid);
123+
AT_CellularContext *curr = _context_list;
124+
while (curr) {
125+
if (cid >= 0) {
126+
if (curr->get_cid() == cid) {
127+
CellularDevice::cellular_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_DISCONNECTED, curr);
128+
break;
129+
}
130+
} else {
131+
CellularDevice::cellular_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_DISCONNECTED);
132+
}
133+
curr = (AT_CellularContext *)curr->_next;
134+
}
135+
}
136+
72137
nsapi_error_t AT_CellularDevice::hard_power_on()
73138
{
74139
return NSAPI_ERROR_OK;

features/cellular/framework/AT/AT_CellularDevice.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,11 @@ class AT_CellularDevice : public CellularDevice {
140140
int _default_timeout;
141141
bool _modem_debug_on;
142142
ATHandler *_at;
143+
144+
private:
145+
void urc_nw_deact();
146+
void urc_pdn_deact();
147+
void send_disconnect_to_context(int cid);
143148
};
144149

145150
} // namespace mbed

0 commit comments

Comments
 (0)