Skip to content

Commit

Permalink
Cellular: Add API to clear CellularDevice
Browse files Browse the repository at this point in the history
A new API `CellularDevice::clear()` to clean-up the modem to a default initial state.
Function is virtual so it can be overridden. The default implementation clears all PDP contexts,
but the the first one if that has APN defined as `nsapi.default-cellular-apn`.

CellularStateMachine calls `clear()` to clean-up the modem on initial `connect()`,
if the flag `cellular.clear-on-connect: true` is defined.
  • Loading branch information
Ari Parkkila authored and hugueskamba committed Sep 10, 2019
1 parent 0f1962e commit 5f8f5fd
Show file tree
Hide file tree
Showing 11 changed files with 135 additions and 1 deletion.
5 changes: 5 additions & 0 deletions UNITTESTS/stubs/AT_CellularDevice_stub.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -256,3 +256,8 @@ void AT_CellularDevice::cellular_callback(nsapi_event_t ev, intptr_t ptr, Cellul
void AT_CellularDevice::set_at_urcs_impl()
{
}

nsapi_error_t AT_CellularDevice::clear()
{
return NSAPI_ERROR_OK;
}
5 changes: 5 additions & 0 deletions UNITTESTS/stubs/AT_CellularNetwork_stub.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,3 +166,8 @@ nsapi_error_t AT_CellularNetwork::set_packet_domain_event_reporting(bool on)
{
return NSAPI_ERROR_OK;
}

nsapi_error_t AT_CellularNetwork::clear()
{
return NSAPI_ERROR_OK;
}
5 changes: 5 additions & 0 deletions UNITTESTS/stubs/CellularDevice_stub.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,8 @@ nsapi_error_t CellularDevice::shutdown()
void CellularDevice::cellular_callback(nsapi_event_t ev, intptr_t ptr, CellularContext *ctx)
{
}

nsapi_error_t CellularDevice::clear()
{
return NSAPI_ERROR_OK;
}
12 changes: 12 additions & 0 deletions features/cellular/framework/API/CellularDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,18 @@ class CellularDevice {
*/
virtual ~CellularDevice();

/** Clear modem to a default initial state
*
* Clear persistent user data from the modem, such as PDP contexts.
*
* @pre All open network services on modem, such as contexts and sockets, must be closed.
* @post Modem power off/on may be needed to clear modem's runtime state.
* @remark CellularStateMachine calls this on connect when `cellular.clear-on-connect: true`.
*
* @return NSAPI_ERROR_OK on success, otherwise modem may be need power cycling
*/
virtual nsapi_error_t clear();

/** Sets the modem up for powering on
* This is equivalent to plugging in the device, i.e., attaching power and serial port.
* In general, hard_power_on and soft_power_on provides a simple hardware abstraction layer
Expand Down
9 changes: 9 additions & 0 deletions features/cellular/framework/AT/AT_CellularDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -624,3 +624,12 @@ void AT_CellularDevice::cellular_callback(nsapi_event_t ev, intptr_t ptr, Cellul
}
CellularDevice::cellular_callback(ev, ptr, ctx);
}

nsapi_error_t AT_CellularDevice::clear()
{
AT_CellularNetwork *net = static_cast<AT_CellularNetwork *>(open_network());
nsapi_error_t err = net->clear();
close_network();

return err;
}
2 changes: 2 additions & 0 deletions features/cellular/framework/AT/AT_CellularDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ class AT_CellularDevice : public CellularDevice {
AT_CellularDevice(FileHandle *fh);
virtual ~AT_CellularDevice();

virtual nsapi_error_t clear();

virtual nsapi_error_t hard_power_on();

virtual nsapi_error_t hard_power_off();
Expand Down
66 changes: 66 additions & 0 deletions features/cellular/framework/AT/AT_CellularNetwork.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -631,3 +631,69 @@ nsapi_error_t AT_CellularNetwork::set_packet_domain_event_reporting(bool on)

return _at.at_cmd_discard("+CGEREP", "=", "%d", on ? 1 : 0);
}

nsapi_error_t AT_CellularNetwork::clear()
{
tr_info("AT_CellularNetwork::clear");

_at.lock();
_at.cmd_start_stop("+CGDCONT", "?");
_at.resp_start("+CGDCONT:");

struct context_s {
int id;
context_s *next;
};
CellularList<context_s> contexts;
while (_at.info_resp()) {
int cid = _at.read_int();
// clear all but the default context
if (cid <= 0) {
continue;
} else if (cid == 1) {
#ifndef MBED_CONF_NSAPI_DEFAULT_CELLULAR_APN
continue;
#else
char pdp_type_from_context[10];
int pdp_type_len = _at.read_string(pdp_type_from_context, sizeof(pdp_type_from_context));
if (pdp_type_len > 0) {
char apn[MAX_ACCESSPOINT_NAME_LENGTH];
int apn_len = _at.read_string(apn, sizeof(apn));
if (apn_len >= 0) {
if (strcmp(apn, MBED_CONF_NSAPI_DEFAULT_CELLULAR_APN) == 0) {
continue;
}
}
}
#endif
}
contexts.add_new()->id = cid;
}
_at.resp_stop();

if (contexts.get_head()) {
// try to detach from network before deleting contexts
(void)detach();
context_s *context = contexts.get_head();
while (context) {
if (_at.at_cmd_discard("+CGDCONT", "=", "%d", context->id) != NSAPI_ERROR_OK) {
tr_warn("Clear context %d failed", context->id);
}
context = context->next;
}
#ifdef MBED_CONF_NSAPI_DEFAULT_CELLULAR_APN
char pdp_type_str[sizeof("IPV4V6")];
if (get_property(PROPERTY_IPV4V6_PDP_TYPE) ||
(get_property(PROPERTY_IPV4_PDP_TYPE) && get_property(PROPERTY_IPV6_PDP_TYPE))) {
strcpy(pdp_type_str, "IPV4V6");
} else if (get_property(PROPERTY_IPV6_PDP_TYPE)) {
strcpy(pdp_type_str, "IPV6");
} else {
strcpy(pdp_type_str, "IP");
}
_at.at_cmd_discard("+CGDCONT", "=", "%d%s%s", 1, pdp_type_str, MBED_CONF_NSAPI_DEFAULT_CELLULAR_APN);
#endif
}

return _at.unlock_return_error();
}
7 changes: 7 additions & 0 deletions features/cellular/framework/AT/AT_CellularNetwork.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,13 @@ class AT_CellularNetwork : public CellularNetwork, public AT_CellularBase {
* Can be overridden by the target class.
*/
virtual void get_context_state_command();

/** Clear the network and contexts to a known default state
*
* @return NSAPI_ERROR_OK on success
*/
nsapi_error_t clear();

private:
void urc_creg();
void urc_cereg();
Expand Down
7 changes: 6 additions & 1 deletion features/cellular/framework/device/CellularDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ MBED_WEAK CellularDevice *CellularDevice::get_target_default_instance()
}

CellularDevice::CellularDevice(FileHandle *fh) : _network_ref_count(0), _sms_ref_count(0),
_info_ref_count(0), _fh(fh), _queue(8 * EVENTS_EVENT_SIZE), _state_machine(0), _nw(0), _status_cb(0)
_info_ref_count(0), _fh(fh), _queue(10 * EVENTS_EVENT_SIZE), _state_machine(0), _nw(0), _status_cb(0)
{
MBED_ASSERT(fh);
set_sim_pin(NULL);
Expand Down Expand Up @@ -250,4 +250,9 @@ void CellularDevice::set_retry_timeout_array(const uint16_t timeout[], int array
}
}

nsapi_error_t CellularDevice::clear()
{
return NSAPI_ERROR_OK;
}

} // namespace mbed
14 changes: 14 additions & 0 deletions features/cellular/framework/device/CellularStateMachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,13 @@ bool CellularStateMachine::device_ready()
}
#endif // MBED_CONF_CELLULAR_DEBUG_AT

#ifdef MBED_CONF_CELLULAR_CLEAR_ON_CONNECT
if (_cellularDevice.clear() != NSAPI_ERROR_OK) {
tr_warning("CellularDevice clear failed");
return false;
}
#endif

send_event_cb(CellularDeviceReady);
_cellularDevice.set_ready_cb(0);

Expand All @@ -364,6 +371,13 @@ void CellularStateMachine::state_device_ready()
if (device_ready()) {
_status = 0;
enter_to_state(STATE_SIM_PIN);
} else {
tr_warning("Power cycle CellularDevice and restart connecting");
(void) _cellularDevice.soft_power_off();
(void) _cellularDevice.hard_power_off();
_status = 0;
_is_retry = true;
enter_to_state(STATE_INIT);
}
} else {
_status = 0;
Expand Down
4 changes: 4 additions & 0 deletions features/cellular/mbed_lib.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@
"offload-dns-queries" : {
"help": "Use modem IP stack for DNS queries, null or numeric simultaneous queries",
"value": null
},
"clear-on-connect" : {
"help": "Clear modem to a known default state on connect()",
"value": true
}
}
}

0 comments on commit 5f8f5fd

Please sign in to comment.