Skip to content

Commit 9d67a8b

Browse files
author
Teppo Järvelin
committed
Cellular: send disconnect to correct ctx
Disconnect was sent to all CellularContext classes even it concerned one specific context. Some disconnect events are still sent to all context classes. These event are coming from network and ment for all context classes or event did not specify cid.
1 parent beed42e commit 9d67a8b

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)