Skip to content

Cellular: Add API to clear CellularDevice #11414

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
Sep 10, 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
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
}
}
}