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.
pull/10402/head
Teppo Järvelin 2019-03-29 15:41:30 +02:00
parent beed42e666
commit 9d67a8b61c
14 changed files with 155 additions and 80 deletions

View File

@ -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) {
@ -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

View File

@ -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;

View File

@ -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();

View File

@ -282,6 +282,12 @@ public: // from NetworkInterface
*/
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,

View File

@ -121,7 +121,7 @@ public:
/** 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);

View File

@ -67,18 +67,18 @@ public:
*/
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

View File

@ -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"
@ -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
@ -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)
@ -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();
@ -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)
@ -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);
}
@ -1002,6 +1003,11 @@ 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) {
@ -1009,7 +1015,7 @@ void AT_CellularContext::cellular_callback(nsapi_event_t ev, intptr_t ptr)
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;
}
}
@ -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);
}
}

View File

@ -131,7 +131,6 @@ protected:
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;
};

View File

@ -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;
@ -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;
@ -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;

View File

@ -140,6 +140,11 @@ public:
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

View File

@ -85,9 +85,13 @@ AT_CellularNetwork::AT_CellularNetwork(ATHandler &atHandler) : AT_CellularBase(a
}
}
_at.set_urc_handler("NO CARRIER", callback(this, &AT_CellularNetwork::urc_no_carrier));
// additional urc to get better disconnect info for application. Not critical.
_at.set_urc_handler("+CGEV:", callback(this, &AT_CellularNetwork::urc_cgev));
if (get_property(AT_CellularBase::PROPERTY_AT_CGEREP)) {
// additional urc to get better disconnect info for application. Not critical.
_at.set_urc_handler("+CGEV: NW DET", callback(this, &AT_CellularNetwork::urc_cgev));
_at.set_urc_handler("+CGEV: ME DET", callback(this, &AT_CellularNetwork::urc_cgev));
}
_at.set_urc_handler("+CCIOTOPTI:", callback(this, &AT_CellularNetwork::urc_cciotopti));
}
@ -100,44 +104,16 @@ AT_CellularNetwork::~AT_CellularNetwork()
}
}
_at.set_urc_handler("NO CARRIER", 0);
_at.set_urc_handler("+CGEV:", 0);
}
void AT_CellularNetwork::urc_no_carrier()
{
tr_info("NO CARRIER");
call_network_cb(NSAPI_STATUS_DISCONNECTED);
if (get_property(AT_CellularBase::PROPERTY_AT_CGEREP)) {
_at.set_urc_handler("+CGEV: ME DET", 0);
_at.set_urc_handler("+CGEV: NW DET", 0);
}
_at.set_urc_handler("+CCIOTOPTI:", 0);
}
void AT_CellularNetwork::urc_cgev()
{
char buf[13];
if (_at.read_string(buf, 13) < 8) { // smallest string length we wan't to compare is 8
return;
}
tr_debug("CGEV: %s", buf);
bool call_cb = false;
// NOTE! If in future there will be 2 or more active contexts we might wan't to read context id also but not for now.
if (memcmp(buf, "NW DETACH", 9) == 0) { // The network has forced a PS detach
call_cb = true;
} else if (memcmp(buf, "ME DETACH", 9) == 0) {// The mobile termination has forced a PS detach.
call_cb = true;
} else if (memcmp(buf, "NW DEACT", 8) == 0) {// The network has forced a context deactivation
call_cb = true;
} else if (memcmp(buf, "ME DEACT", 8) == 0) {// The mobile termination has forced a context deactivation
call_cb = true;
} else if (memcmp(buf, "NW PDN DEACT", 12) == 0) {// The network has deactivated a context
call_cb = true;
} else if (memcmp(buf, "ME PDN DEACT", 12) == 0) {// The mobile termination has deactivated a context.
call_cb = true;
}
if (call_cb) {
call_network_cb(NSAPI_STATUS_DISCONNECTED);
}
call_network_cb(NSAPI_STATUS_DISCONNECTED);
}
void AT_CellularNetwork::read_reg_params_and_compare(RegistrationType type)
@ -159,8 +135,7 @@ void AT_CellularNetwork::read_reg_params_and_compare(RegistrationType type)
_reg_params._status = reg_params._status;
data.status_data = reg_params._status;
_connection_status_cb((nsapi_event_t)CellularRegistrationStatusChanged, (intptr_t)&data);
if (!(reg_params._status == RegisteredHomeNetwork ||
reg_params._status == RegisteredRoaming)) {
if (reg_params._status == NotRegistered) { // Other states means that we are trying to connect or connected
if (previous_registration_status == RegisteredHomeNetwork ||
previous_registration_status == RegisteredRoaming) {
if (type != C_REG) {// we are interested only if we drop from packet network
@ -713,8 +688,8 @@ nsapi_error_t AT_CellularNetwork::set_packet_domain_event_reporting(bool on)
}
_at.lock();
_at.cmd_start("AT+CGEREP=");// 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.write_int(on ? 1 : 0);
_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();

View File

@ -111,8 +111,6 @@ protected:
*/
virtual void get_context_state_command();
private:
// "NO CARRIER" urc
void urc_no_carrier();
void urc_creg();
void urc_cereg();
void urc_cgreg();

View File

@ -68,6 +68,11 @@ CellularDevice *CellularContext::get_device() const
return _device;
}
int CellularContext::get_cid() const
{
return _cid;
}
void CellularContext::do_connect_with_retry()
{
if (_cb_data.final_try) {

View File

@ -43,7 +43,7 @@ static const intptr_t cellular_properties[AT_CellularBase::PROPERTY_MAX] = {
0, // PROPERTY_IPV6_STACK
0, // PROPERTY_IPV4V6_STACK
0, // PROPERTY_NON_IP_PDP_TYPE
1, // PROPERTY_AT_CGEREP
0, // PROPERTY_AT_CGEREP
};
QUECTEL_BC95::QUECTEL_BC95(FileHandle *fh) : AT_CellularDevice(fh)