Cellular: Added dynamic alloc and destruction to easycellular.

Now application can call connect and disconnect multiple times and resources are freed and constructed properly.
Also whole easycellular can be deleted and constructed again.
pull/6792/head
Teppo Järvelin 2018-05-02 14:50:05 +03:00
parent d08c819830
commit b22a16fe4a
6 changed files with 74 additions and 34 deletions

View File

@ -70,18 +70,28 @@ CellularConnectionFSM::CellularConnectionFSM() :
CellularConnectionFSM::~CellularConnectionFSM()
{
stop();
delete _cellularDevice;
}
void CellularConnectionFSM::stop()
{
tr_info("CellularConnectionUtil::stop");
_queue.cancel(_event_id);
_queue.break_dispatch();
if (_queue_thread) {
_queue_thread->terminate();
delete _queue_thread;
_queue_thread = NULL;
}
delete _cellularDevice;
_cellularDevice = NULL;
// _cellularDevice closes all interfaces in destructor
_power = NULL;
_network = NULL;
_sim = NULL;
_state = STATE_INIT;
_next_state = _state;
}
nsapi_error_t CellularConnectionFSM::init()
@ -98,6 +108,7 @@ nsapi_error_t CellularConnectionFSM::init()
stop();
return NSAPI_ERROR_NO_MEMORY;
}
_network = _cellularDevice->open_network(_serial);
if (!_network) {
stop();
@ -360,6 +371,7 @@ nsapi_error_t CellularConnectionFSM::continue_from_state(CellularState state)
nsapi_error_t CellularConnectionFSM::continue_to_state(CellularState state)
{
MBED_ASSERT(_cellularDevice);
_retry_count = 0;
if (state < _state) {
_state = state;
@ -647,8 +659,13 @@ void CellularConnectionFSM::set_callback(mbed::Callback<bool(int, int)> status_c
void CellularConnectionFSM::attach(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb)
{
MBED_ASSERT(_network);
_event_status_cb = status_cb;
_network->attach(callback(this, &CellularConnectionFSM::network_callback));
if (status_cb) {
_network->attach(callback(this, &CellularConnectionFSM::network_callback));
} else {
_network->attach(NULL);
}
}
void CellularConnectionFSM::network_callback(nsapi_event_t ev, intptr_t ptr)

View File

@ -102,7 +102,8 @@ public:
*/
nsapi_error_t start_dispatch();
/** Stop event queue dispatching and close cellular interfaces
/** Stop event queue dispatching and close cellular interfaces. After calling stop(), init() must be called
* before any other methods.
*/
void stop();
@ -153,6 +154,7 @@ public:
* @return string format of the given state
*/
const char* get_state_string(CellularState state);
private:
bool power_on();
bool open_sim();

View File

@ -76,7 +76,8 @@ EasyCellularConnection::EasyCellularConnection(bool debug) :
EasyCellularConnection::~EasyCellularConnection()
{
_cellularConnectionFSM.stop();
_cellularConnectionFSM.set_callback(NULL);
_cellularConnectionFSM.attach(NULL);
}
nsapi_error_t EasyCellularConnection::init()
@ -118,7 +119,7 @@ void EasyCellularConnection::set_credentials(const char *apn, const char *uname,
}
#endif // #if USE_APN_LOOKUP
} else {
//if get_network() returns NULL it means there was not enough memory for
//if get_network() returns NULL it means there was not enough memory for
//an AT_CellularNetwork element during CellularConnectionFSM initialization
tr_error("There was not enough memory during CellularConnectionFSM initialization");
}
@ -224,13 +225,19 @@ nsapi_error_t EasyCellularConnection::disconnect()
{
_credentials_err = NSAPI_ERROR_OK;
_is_connected = false;
_is_initialized = false;
#if USE_APN_LOOKUP
_credentials_set = false;
#endif // #if USE_APN_LOOKUP
if (!_cellularConnectionFSM.get_network()) {
return NSAPI_ERROR_NO_CONNECTION;
nsapi_error_t err = NSAPI_ERROR_OK;
if (_cellularConnectionFSM.get_network()) {
err = _cellularConnectionFSM.get_network()->disconnect();
}
return _cellularConnectionFSM.get_network()->disconnect();
_cellularConnectionFSM.stop();
return err;
}
bool EasyCellularConnection::is_connected()

View File

@ -63,7 +63,6 @@ static const uint8_t map_3gpp_errors[][2] = {
ATHandler::ATHandler(FileHandle *fh, EventQueue &queue, int timeout, const char *output_delimiter, uint16_t send_delay) :
_nextATHandler(0),
_fileHandle(fh),
_queue(queue),
_last_err(NSAPI_ERROR_OK),
_last_3gpp_error(0),
@ -109,9 +108,7 @@ ATHandler::ATHandler(FileHandle *fh, EventQueue &queue, int timeout, const char
set_tag(&_info_stop, CRLF);
set_tag(&_elem_stop, ")");
_fileHandle->set_blocking(false);
set_filehandle_sigio();
set_file_handle(fh);
}
void ATHandler::enable_debug(bool enable)
@ -153,7 +150,20 @@ FileHandle *ATHandler::get_file_handle()
void ATHandler::set_file_handle(FileHandle *fh)
{
_fh_sigio_set = false;
_fileHandle = fh;
_fileHandle->set_blocking(false);
set_filehandle_sigio();
}
void ATHandler::set_filehandle_sigio()
{
if (_fh_sigio_set) {
return;
}
_fileHandle->sigio(mbed::Callback<void()>(this, &ATHandler::event));
_fh_sigio_set = true;
}
nsapi_error_t ATHandler::set_urc_handler(const char *prefix, mbed::Callback<void()> callback)
@ -310,15 +320,6 @@ void ATHandler::process_oob()
unlock();
}
void ATHandler::set_filehandle_sigio()
{
if (_fh_sigio_set) {
return;
}
_fileHandle->sigio(mbed::Callback<void()>(this, &ATHandler::event));
_fh_sigio_set = true;
}
void ATHandler::reset_buffer()
{
tr_debug("%s", __func__);
@ -1023,8 +1024,8 @@ void ATHandler::cmd_start(const char* cmd)
if (time_difference < (uint64_t)_at_send_delay) {
wait_ms((uint64_t)_at_send_delay - time_difference);
tr_debug("AT wait %llu %llu", current_time, _last_response_stop);
}
}
}
}
at_debug("AT cmd %s (err %d)\n", cmd, _last_err);
@ -1088,7 +1089,7 @@ void ATHandler::cmd_stop()
size_t ATHandler::write_bytes(const uint8_t *data, size_t len)
{
at_debug("AT write bytes %d (err %d)\n", len, _last_err);
if (_last_err != NSAPI_ERROR_OK) {
return 0;
}

View File

@ -86,12 +86,6 @@ public:
*/
FileHandle *get_file_handle();
/** Set file handle, which is used for reading AT responses and writing AT commands
*
* @param fh file handle used for reading AT responses and writing AT commands
*/
void set_file_handle(FileHandle *fh);
/** Locks the mutex for file handle if AT_HANDLER_MUTEX is defined.
*/
void lock();
@ -165,6 +159,11 @@ public:
*/
void clear_error();
/**
* Flushes the underlying stream
*/
void flush();
/** Tries to find oob's from the AT response. Call the urc callback if one is found.
*/
void process_oob();
@ -173,10 +172,11 @@ public:
*/
void set_filehandle_sigio();
/**
* Flushes the underlying stream
/** Set file handle, which is used for reading AT responses and writing AT commands
*
* @param fh file handle used for reading AT responses and writing AT commands
*/
void flush();
void set_file_handle(FileHandle *fh);
protected:
void event();

View File

@ -48,6 +48,19 @@ AT_CellularNetwork::AT_CellularNetwork(ATHandler &atHandler) : AT_CellularBase(a
AT_CellularNetwork::~AT_CellularNetwork()
{
#if NSAPI_PPP_AVAILABLE
(void)disconnect();
#else
delete _stack;
#endif // NSAPI_PPP_AVAILABLE
for (int type = 0; type < CellularNetwork::C_MAX; type++) {
if (has_registration((RegistrationType)type)) {
_at.remove_urc_handler(at_reg[type].urc_prefix, _urc_funcs[type]);
}
}
_at.remove_urc_handler("NO CARRIER", callback(this, &AT_CellularNetwork::urc_no_carrier));
free_credentials();
}