Merge pull request #11414 from AriParkkila/cell-clear

Cellular: Add API to clear CellularDevice
pull/11450/head
Martin Kojtal 2019-09-10 13:58:17 +02:00 committed by GitHub
commit 8f1bf43335
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 135 additions and 1 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -39,6 +39,8 @@ public:
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();

View File

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

View File

@ -110,6 +110,13 @@ protected:
* 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();

View File

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

View File

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

View File

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