diff --git a/UNITTESTS/features/cellular/framework/AT/at_cellularbase/unittest.cmake b/UNITTESTS/features/cellular/framework/AT/at_cellularbase/unittest.cmake index eab77c34eb..32d9d47208 100644 --- a/UNITTESTS/features/cellular/framework/AT/at_cellularbase/unittest.cmake +++ b/UNITTESTS/features/cellular/framework/AT/at_cellularbase/unittest.cmake @@ -16,6 +16,7 @@ set(unittest-includes ${unittest-includes} # Source files set(unittest-sources ../features/cellular/framework/AT/AT_CellularBase.cpp + ../features/cellular/framework/AT/ATHandler_factory.cpp ) # Test files diff --git a/UNITTESTS/features/cellular/framework/AT/at_cellularcontext/unittest.cmake b/UNITTESTS/features/cellular/framework/AT/at_cellularcontext/unittest.cmake index 1d9c56320a..f10bf17d26 100644 --- a/UNITTESTS/features/cellular/framework/AT/at_cellularcontext/unittest.cmake +++ b/UNITTESTS/features/cellular/framework/AT/at_cellularcontext/unittest.cmake @@ -14,6 +14,7 @@ set(unittest-includes ${unittest-includes} # Source files set(unittest-sources ../features/cellular/framework/AT/AT_CellularContext.cpp + ../features/cellular/framework/AT/ATHandler_factory.cpp ../features/cellular/framework/common/CellularUtil.cpp ) diff --git a/UNITTESTS/features/cellular/framework/AT/at_cellulardevice/at_cellulardevicetest.cpp b/UNITTESTS/features/cellular/framework/AT/at_cellulardevice/at_cellulardevicetest.cpp index 8609e8a38a..622844aecb 100644 --- a/UNITTESTS/features/cellular/framework/AT/at_cellulardevice/at_cellulardevicetest.cpp +++ b/UNITTESTS/features/cellular/framework/AT/at_cellulardevice/at_cellulardevicetest.cpp @@ -61,6 +61,16 @@ TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_get_at_handler) EXPECT_TRUE(dev.open_power(&fh1)); ATHandler_stub::fh_value = NULL; + + AT_CellularDevice *dev2 = new AT_CellularDevice(&fh1); + EXPECT_TRUE(dev2->open_information(&fh1)); + ATHandler *at = dev2->get_at_handler(); + EXPECT_TRUE(at->get_ref_count() == 4); + delete dev2; + EXPECT_TRUE(at->get_ref_count() == 3); + AT_CellularDevice dev3(&fh1); + EXPECT_TRUE(dev3.release_at_handler(at) == NSAPI_ERROR_OK); + EXPECT_TRUE(ATHandler_stub::ref_count == 2); } TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_open_network) @@ -211,7 +221,7 @@ TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_close_information) AT_CellularBase_stub::handler_value = AT_CellularBase_stub::handler_at_constructor_value; dev.close_information(); - EXPECT_TRUE(ATHandler_stub::ref_count == 1); + EXPECT_TRUE(ATHandler_stub::ref_count == kATHandler_destructor_ref_ount); ATHandler_stub::fh_value = NULL; } @@ -276,13 +286,21 @@ TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_create_delete_context) FileHandle_stub fh1; AT_CellularDevice *dev = new AT_CellularDevice(&fh1); + ATHandler *at = dev->get_at_handler(); + EXPECT_TRUE(at->get_ref_count() == 1); + EXPECT_TRUE(dev->release_at_handler(at) == NSAPI_ERROR_OK); + CellularContext *ctx = dev->create_context(NULL); delete dev; dev = new AT_CellularDevice(&fh1); + at = dev->get_at_handler(); + EXPECT_TRUE(at->get_ref_count() == 1); ctx = dev->create_context(NULL); CellularContext *ctx1 = dev->create_context(&fh1); + EXPECT_TRUE(at->get_ref_count() == 3); CellularContext *ctx2 = dev->create_context(&fh1); + EXPECT_TRUE(at->get_ref_count() == 4); EXPECT_TRUE(ctx); EXPECT_TRUE(ctx1); @@ -293,13 +311,21 @@ TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_create_delete_context) EXPECT_TRUE(xx); dev->delete_context(ctx); + EXPECT_TRUE(at->get_ref_count() == 3); dev->delete_context(ctx1); + EXPECT_TRUE(at->get_ref_count() == 2); dev->delete_context(NULL); + EXPECT_TRUE(at->get_ref_count() == 2); dev->delete_context(ctx2); + EXPECT_TRUE(at->get_ref_count() == 1); ctx = dev->create_context(NULL); + EXPECT_TRUE(at->get_ref_count() == 2); ctx1 = dev->create_context(&fh1); + EXPECT_TRUE(at->get_ref_count() == 3); ctx2 = dev->create_context(&fh1); + EXPECT_TRUE(at->get_ref_count() == 4); + EXPECT_TRUE(dev->release_at_handler(at) == NSAPI_ERROR_OK); EXPECT_TRUE(ctx); EXPECT_TRUE(ctx1); EXPECT_TRUE(ctx1 != ctx); diff --git a/UNITTESTS/features/cellular/framework/AT/at_cellulardevice/unittest.cmake b/UNITTESTS/features/cellular/framework/AT/at_cellulardevice/unittest.cmake index 0897cb4a9e..5ce257eab7 100644 --- a/UNITTESTS/features/cellular/framework/AT/at_cellulardevice/unittest.cmake +++ b/UNITTESTS/features/cellular/framework/AT/at_cellulardevice/unittest.cmake @@ -18,6 +18,7 @@ set(unittest-includes ${unittest-includes} set(unittest-sources stubs/randLIB_stub.c ../features/cellular/framework/AT/AT_CellularDevice.cpp + ../features/cellular/framework/AT/ATHandler_factory.cpp ) # Test files diff --git a/UNITTESTS/features/cellular/framework/AT/athandler/athandlertest.cpp b/UNITTESTS/features/cellular/framework/AT/athandler/athandlertest.cpp index 3f5d033a72..211f80cc18 100644 --- a/UNITTESTS/features/cellular/framework/AT/athandler/athandlertest.cpp +++ b/UNITTESTS/features/cellular/framework/AT/athandler/athandlertest.cpp @@ -86,6 +86,38 @@ TEST_F(TestATHandler, test_ATHandler_set_file_handle) at.set_file_handle(&fh2); } +TEST_F(TestATHandler, test_ATHandler_list) +{ + EventQueue que; + FileHandle_stub fh1; + + ATHandler::set_at_timeout_list(1000, false); + ATHandler::set_debug_list(false); + + ATHandler *at1 = ATHandler::get_instance(&fh1, que, 0, ",", 0, 0); + EXPECT_TRUE(at1->get_ref_count() == 1); + + ATHandler::set_at_timeout_list(1000, false); + ATHandler::set_debug_list(true); + + EXPECT_TRUE(ATHandler::get_instance(NULL, que, 0, ",", 0, 0) == NULL); + + ATHandler *at2 = ATHandler::get_instance(&fh1, que, 0, ",", 0, 0); + EXPECT_TRUE(at1->get_ref_count() == 2); + EXPECT_TRUE(at2->get_ref_count() == 2); + + ATHandler::set_at_timeout_list(2000, true); + ATHandler::set_debug_list(false); + + EXPECT_TRUE(at1->close() == NSAPI_ERROR_OK); + EXPECT_TRUE(at2->get_ref_count() == 1); + EXPECT_TRUE(at2->close() == NSAPI_ERROR_OK); + EXPECT_TRUE(at1->close() == NSAPI_ERROR_PARAMETER); + + ATHandler::set_at_timeout_list(1000, false); + ATHandler::set_debug_list(false); +} + TEST_F(TestATHandler, test_ATHandler_lock) { EventQueue que; diff --git a/UNITTESTS/features/cellular/framework/AT/athandler/unittest.cmake b/UNITTESTS/features/cellular/framework/AT/athandler/unittest.cmake index 26bf570221..2e9dc4f1da 100644 --- a/UNITTESTS/features/cellular/framework/AT/athandler/unittest.cmake +++ b/UNITTESTS/features/cellular/framework/AT/athandler/unittest.cmake @@ -14,6 +14,7 @@ set(unittest-includes ${unittest-includes} # Source files set(unittest-sources ../features/cellular/framework/AT/ATHandler.cpp + ../features/cellular/framework/AT/ATHandler_factory.cpp ../features/cellular/framework/common/CellularUtil.cpp ) diff --git a/UNITTESTS/stubs/ATHandler_stub.cpp b/UNITTESTS/stubs/ATHandler_stub.cpp index 54003807f5..5ae5d4fca6 100644 --- a/UNITTESTS/stubs/ATHandler_stub.cpp +++ b/UNITTESTS/stubs/ATHandler_stub.cpp @@ -57,10 +57,11 @@ int ATHandler_stub::urc_amount = 0; mbed::Callback ATHandler_stub::callback[kATHandler_urc_table_max_size]; char *ATHandler_stub::urc_string_table[kATHandler_urc_table_max_size]; -ATHandler::ATHandler(FileHandle *fh, EventQueue &queue, int timeout, const char *output_delimiter, uint16_t send_delay) : +ATHandler::ATHandler(FileHandle *fh, EventQueue &queue, uint32_t timeout, const char *output_delimiter, uint16_t send_delay) : _nextATHandler(0), _fileHandle(fh), - _queue(queue) + _queue(queue), + _ref_count(1) { ATHandler_stub::ref_count = 1; @@ -95,22 +96,25 @@ ATHandler::~ATHandler() void ATHandler::inc_ref_count() { - ATHandler_stub::ref_count++; + _ref_count++; + ATHandler_stub::ref_count = _ref_count; } void ATHandler::dec_ref_count() { - ATHandler_stub::ref_count--; + _ref_count--; + ATHandler_stub::ref_count = _ref_count; } int ATHandler::get_ref_count() { - return ATHandler_stub::ref_count; + return _ref_count; } FileHandle *ATHandler::get_file_handle() { - return ATHandler_stub::fh_value; + ATHandler_stub::fh_value = (FileHandle_stub *)_fileHandle; + return _fileHandle; } void ATHandler::set_file_handle(FileHandle *fh) diff --git a/UNITTESTS/stubs/AT_CellularBase_stub.cpp b/UNITTESTS/stubs/AT_CellularBase_stub.cpp index 179c2e42e1..1c7f25a4bf 100644 --- a/UNITTESTS/stubs/AT_CellularBase_stub.cpp +++ b/UNITTESTS/stubs/AT_CellularBase_stub.cpp @@ -34,7 +34,8 @@ AT_CellularBase::AT_CellularBase(ATHandler &at) : _at(at) ATHandler &AT_CellularBase::get_at_handler() { - return *AT_CellularBase_stub::handler_value; + AT_CellularBase_stub::handler_value = &_at; + return _at; } device_err_t AT_CellularBase::get_device_error() const diff --git a/UNITTESTS/stubs/AT_CellularDevice_stub.cpp b/UNITTESTS/stubs/AT_CellularDevice_stub.cpp index 111b6460e3..7ef169e736 100644 --- a/UNITTESTS/stubs/AT_CellularDevice_stub.cpp +++ b/UNITTESTS/stubs/AT_CellularDevice_stub.cpp @@ -27,22 +27,29 @@ AT_CellularDevice::AT_CellularDevice(FileHandle *fh) : CellularDevice(fh), _netw _sim(0), _power(0), _information(0), _context_list(0), _default_timeout(DEFAULT_AT_TIMEOUT), _modem_debug_on(false) { - _atHandlers = new ATHandler(fh, _queue, 0, ","); } AT_CellularDevice::~AT_CellularDevice() { - delete _atHandlers; } ATHandler *AT_CellularDevice::get_at_handler(FileHandle *fileHandle) { - return _atHandlers; + return ATHandler::get_instance(fileHandle, _queue, _default_timeout, "\r", get_send_delay(), _modem_debug_on); } -void AT_CellularDevice::release_at_handler(ATHandler *at_handler) +ATHandler *AT_CellularDevice::get_at_handler() { + return get_at_handler(NULL); +} +nsapi_error_t AT_CellularDevice::release_at_handler(ATHandler *at_handler) +{ + if (at_handler) { + return at_handler->close(); + } else { + return NSAPI_ERROR_PARAMETER; + } } CellularContext *create_context(FileHandle *fh = NULL, const char *apn = MBED_CONF_NSAPI_DEFAULT_CELLULAR_APN) @@ -57,7 +64,7 @@ void delete_context(CellularContext *context) CellularNetwork *AT_CellularDevice::open_network(FileHandle *fh) { - return new AT_CellularNetwork(*_atHandlers); + return new AT_CellularNetwork(*ATHandler::get_instance(fh, _queue, _default_timeout, "\r", get_send_delay(), _modem_debug_on)); } CellularSMS *AT_CellularDevice::open_sms(FileHandle *fh) diff --git a/UNITTESTS/target_h/myCellularDevice.h b/UNITTESTS/target_h/myCellularDevice.h index a157f8e4ed..28dfb8a1ac 100644 --- a/UNITTESTS/target_h/myCellularDevice.h +++ b/UNITTESTS/target_h/myCellularDevice.h @@ -119,6 +119,14 @@ public: { CellularDevice::cellular_callback(ev, ptr); } + virtual ATHandler *get_at_handler() + { + return NULL; + } + virtual nsapi_error_t release_at_handler(ATHandler *at_handler) + { + return NSAPI_ERROR_OK; + } AT_CellularNetwork *_network; AT_CellularContext *_context_list; }; diff --git a/features/cellular/framework/API/CellularDevice.h b/features/cellular/framework/API/CellularDevice.h index e42bad08e6..b869f5291e 100644 --- a/features/cellular/framework/API/CellularDevice.h +++ b/features/cellular/framework/API/CellularDevice.h @@ -21,6 +21,7 @@ #include "CellularTargets.h" #include "CellularStateMachine.h" #include "Callback.h" +#include "ATHandler.h" namespace mbed { @@ -249,6 +250,20 @@ public: */ virtual CellularContext *get_context_list() const; + /** Get the current ATHandler instance in use for debug purposes etc. + * Once use has been finished call to release_at_handler() has to be made + * + * @return Pointer to the ATHandler in use + */ + virtual ATHandler *get_at_handler() = 0; + + /** Release the ATHandler taken into use with get_at_handler() + * + * @param at_handler + * @return NSAPI_ERROR_OK on success, NSAPI_ERROR_PARAMETER on failure + */ + virtual nsapi_error_t release_at_handler(ATHandler *at_handler) = 0; + protected: friend class AT_CellularNetwork; friend class AT_CellularContext; diff --git a/features/cellular/framework/AT/ATHandler.cpp b/features/cellular/framework/AT/ATHandler.cpp index 26129793f4..6da6dc9c56 100644 --- a/features/cellular/framework/AT/ATHandler.cpp +++ b/features/cellular/framework/AT/ATHandler.cpp @@ -60,7 +60,7 @@ static const uint8_t map_3gpp_errors[][2] = { { 146, 46 }, { 178, 65 }, { 179, 66 }, { 180, 48 }, { 181, 83 }, { 171, 49 }, }; -ATHandler::ATHandler(FileHandle *fh, EventQueue &queue, int timeout, const char *output_delimiter, uint16_t send_delay) : +ATHandler::ATHandler(FileHandle *fh, EventQueue &queue, uint32_t timeout, const char *output_delimiter, uint16_t send_delay) : _nextATHandler(0), _fileHandle(fh), _queue(queue), diff --git a/features/cellular/framework/AT/ATHandler.h b/features/cellular/framework/AT/ATHandler.h index 3d7a128ca5..4135b96d50 100644 --- a/features/cellular/framework/AT/ATHandler.h +++ b/features/cellular/framework/AT/ATHandler.h @@ -74,7 +74,7 @@ public: * @param output_delimiter delimiter used when parsing at responses, "\r" should be used as output_delimiter * @param send_delay the minimum delay in ms between the end of last response and the beginning of a new command */ - ATHandler(FileHandle *fh, events::EventQueue &queue, int timeout, const char *output_delimiter, uint16_t send_delay = 0); + ATHandler(FileHandle *fh, events::EventQueue &queue, uint32_t timeout, const char *output_delimiter, uint16_t send_delay = 0); virtual ~ATHandler(); /** Return used file handle. @@ -83,6 +83,32 @@ public: */ FileHandle *get_file_handle(); + /** Get a new ATHandler instance, and update the linked list. Once the use of the ATHandler + * has finished, call to close() has to be made + * + * @param fileHandle filehandle used for reading AT responses and writing AT commands. + * If there is already an ATHandler with the same fileHandle pointer, + * then a pointer to that ATHandler instance will be returned with + * that ATHandler's queue, timeout, delimiter, send_delay and debug_on + * values + * @param queue Event queue used to transfer sigio events to this thread + * @param timeout Timeout when reading for AT response + * @param delimiter delimiter used when parsing at responses, "\r" should be used as output_delimiter + * @param send_delay the minimum delay in ms between the end of last response and the beginning of a new command + * @param debug_on Set true to enable debug traces + * @return NULL, if fileHandle is not set, or a pointer to an existing ATHandler, if the fileHandle is + * already in use. Otherwise a pointer to a new ATHandler instance is returned + */ + static ATHandler *get_instance(FileHandle *fileHandle, events::EventQueue &queue, uint32_t timeout, + const char *delimiter, uint16_t send_delay, bool debug_on); + + /** Close and delete the current ATHandler instance, if the reference count to it is 0. + * Close() can be only called, if the ATHandler was opened with get_instance() + * + * @return NSAPI_ERROR_OK on success, NSAPI_ERROR_PARAMETER on failure + */ + nsapi_error_t close(); + /** Locks the mutex for file handle if AT_HANDLER_MUTEX is defined. */ void lock(); @@ -127,10 +153,14 @@ public: device_err_t get_last_device_error() const; /** Increase reference count. Used for counting references to this instance. + * Note that this should be used with care, if the ATHandler was taken into use + * with get_instance() */ void inc_ref_count(); /** Decrease reference count. Used for counting references to this instance. + * Note that this should be used with care, if the ATHandler was taken into use + * with get_instance() */ void dec_ref_count(); @@ -147,6 +177,13 @@ public: */ void set_at_timeout(uint32_t timeout_milliseconds, bool default_timeout = false); + /** Set timeout in milliseconds for all ATHandlers in the _atHandlers list + * + * @param timeout_milliseconds Timeout in milliseconds + * @param default_timeout Store as default timeout + */ + static void set_at_timeout_list(uint32_t timeout_milliseconds, bool default_timeout = false); + /** Restore timeout to previous timeout. Handy if there is a need to change timeout temporarily. */ void restore_at_timeout(); @@ -222,6 +259,8 @@ private: int32_t _ref_count; bool _is_fh_usable; + static ATHandler *_atHandlers; + //************************************* public: @@ -398,6 +437,12 @@ public: // just for debugging */ void set_debug(bool debug_on); + /** Set debug_on for all ATHandlers in the _atHandlers list + * + * @param debug_on Set true to enable debug traces + */ + static void set_debug_list(bool debug_on); + private: // should fit any prefix and int diff --git a/features/cellular/framework/AT/ATHandler_factory.cpp b/features/cellular/framework/AT/ATHandler_factory.cpp new file mode 100644 index 0000000000..0fcb42d20f --- /dev/null +++ b/features/cellular/framework/AT/ATHandler_factory.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2018, Arm Limited and affiliates. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ATHandler.h" +#include "SingletonPtr.h" + +using namespace mbed; + +ATHandler *ATHandler::_atHandlers = NULL; + +// each parser is associated with one filehandle (that is UART) +ATHandler *ATHandler::get_instance(FileHandle *fileHandle, events::EventQueue &queue, uint32_t timeout, + const char *delimiter, uint16_t send_delay, bool debug_on) +{ + if (!fileHandle) { + return NULL; + } + + singleton_lock(); + ATHandler *atHandler = _atHandlers; + while (atHandler) { + if (atHandler->get_file_handle() == fileHandle) { + atHandler->inc_ref_count(); + singleton_unlock(); + return atHandler; + } + atHandler = atHandler->_nextATHandler; + } + + atHandler = new ATHandler(fileHandle, queue, timeout, delimiter, send_delay); + if (debug_on) { + atHandler->set_debug(debug_on); + } + atHandler->_nextATHandler = _atHandlers; + _atHandlers = atHandler; + + singleton_unlock(); + return atHandler; +} + +nsapi_error_t ATHandler::close() +{ + if (get_ref_count() == 0) { + return NSAPI_ERROR_PARAMETER; + } + + singleton_lock(); + dec_ref_count(); + if (get_ref_count() == 0) { + // we can delete this at_handler + ATHandler *atHandler = _atHandlers; + ATHandler *prev = NULL; + while (atHandler) { + if (atHandler == this) { + if (prev == NULL) { + _atHandlers = _atHandlers->_nextATHandler; + } else { + prev->_nextATHandler = atHandler->_nextATHandler; + } + delete this; + break; + } else { + prev = atHandler; + atHandler = atHandler->_nextATHandler; + } + } + } + singleton_unlock(); + return NSAPI_ERROR_OK; +} + +void ATHandler::set_at_timeout_list(uint32_t timeout_milliseconds, bool default_timeout) +{ + ATHandler *atHandler = _atHandlers; + singleton_lock(); + while (atHandler) { + atHandler->set_at_timeout(timeout_milliseconds, default_timeout); + atHandler = atHandler->_nextATHandler; + } + singleton_unlock(); +} + +void ATHandler::set_debug_list(bool debug_on) +{ + ATHandler *atHandler = _atHandlers; + singleton_lock(); + while (atHandler) { + atHandler->set_debug(debug_on); + atHandler = atHandler->_nextATHandler; + } + singleton_unlock(); +} diff --git a/features/cellular/framework/AT/AT_CellularDevice.cpp b/features/cellular/framework/AT/AT_CellularDevice.cpp index d04a15b113..0ab15c60bf 100644 --- a/features/cellular/framework/AT/AT_CellularDevice.cpp +++ b/features/cellular/framework/AT/AT_CellularDevice.cpp @@ -33,7 +33,7 @@ using namespace mbed; #define DEFAULT_AT_TIMEOUT 1000 // at default timeout in milliseconds -AT_CellularDevice::AT_CellularDevice(FileHandle *fh) : CellularDevice(fh), _atHandlers(0), _network(0), _sms(0), +AT_CellularDevice::AT_CellularDevice(FileHandle *fh) : CellularDevice(fh), _network(0), _sms(0), _sim(0), _power(0), _information(0), _context_list(0), _default_timeout(DEFAULT_AT_TIMEOUT), _modem_debug_on(false) { @@ -60,15 +60,10 @@ AT_CellularDevice::~AT_CellularDevice() AT_CellularContext *next; while (curr) { next = (AT_CellularContext *)curr->_next; + ATHandler *at = &curr->get_at_handler(); delete curr; curr = next; - } - - ATHandler *atHandler = _atHandlers; - while (atHandler) { - ATHandler *old = atHandler; - atHandler = atHandler->_nextATHandler; - delete old; + release_at_handler(at); } } @@ -78,49 +73,22 @@ ATHandler *AT_CellularDevice::get_at_handler(FileHandle *fileHandle) if (!fileHandle) { fileHandle = _fh; } - ATHandler *atHandler = _atHandlers; - while (atHandler) { - if (atHandler->get_file_handle() == fileHandle) { - atHandler->inc_ref_count(); - return atHandler; - } - atHandler = atHandler->_nextATHandler; - } - atHandler = new ATHandler(fileHandle, _queue, _default_timeout, "\r", get_send_delay()); - if (_modem_debug_on) { - atHandler->set_debug(_modem_debug_on); - } - atHandler->_nextATHandler = _atHandlers; - _atHandlers = atHandler; - - return atHandler; + return ATHandler::get_instance(fileHandle, _queue, _default_timeout, + "\r", get_send_delay(), _modem_debug_on); } -void AT_CellularDevice::release_at_handler(ATHandler *at_handler) +ATHandler *AT_CellularDevice::get_at_handler() { - if (!at_handler) { - return; - } - at_handler->dec_ref_count(); - if (at_handler->get_ref_count() == 0) { - // we can delete this at_handler - ATHandler *atHandler = _atHandlers; - ATHandler *prev = NULL; - while (atHandler) { - if (atHandler == at_handler) { - if (prev == NULL) { - _atHandlers = _atHandlers->_nextATHandler; - } else { - prev->_nextATHandler = atHandler->_nextATHandler; - } - delete atHandler; - break; - } else { - prev = atHandler; - atHandler = atHandler->_nextATHandler; - } - } + return get_at_handler(NULL); +} + +nsapi_error_t AT_CellularDevice::release_at_handler(ATHandler *at_handler) +{ + if (at_handler) { + return at_handler->close(); + } else { + return NSAPI_ERROR_PARAMETER; } } @@ -173,7 +141,13 @@ void AT_CellularDevice::delete_context(CellularContext *context) prev = curr; curr = (AT_CellularContext *)curr->_next; } + curr = (AT_CellularContext *)context; + ATHandler *at = NULL; + if (curr) { + at = &curr->get_at_handler(); + } delete (AT_CellularContext *)context; + release_at_handler(at); } CellularNetwork *AT_CellularDevice::open_network(FileHandle *fh) @@ -340,11 +314,7 @@ void AT_CellularDevice::set_timeout(int timeout) { _default_timeout = timeout; - ATHandler *atHandler = _atHandlers; - while (atHandler) { - atHandler->set_at_timeout(_default_timeout, true); // set as default timeout - atHandler = atHandler->_nextATHandler; - } + ATHandler::set_at_timeout_list(_default_timeout, true); } uint16_t AT_CellularDevice::get_send_delay() const @@ -356,11 +326,7 @@ void AT_CellularDevice::modem_debug_on(bool on) { _modem_debug_on = on; - ATHandler *atHandler = _atHandlers; - while (atHandler) { - atHandler->set_debug(_modem_debug_on); - atHandler = atHandler->_nextATHandler; - } + ATHandler::set_debug_list(_modem_debug_on); } nsapi_error_t AT_CellularDevice::init_module() diff --git a/features/cellular/framework/AT/AT_CellularDevice.h b/features/cellular/framework/AT/AT_CellularDevice.h index 8caf65b5da..9b171a724b 100644 --- a/features/cellular/framework/AT/AT_CellularDevice.h +++ b/features/cellular/framework/AT/AT_CellularDevice.h @@ -72,15 +72,16 @@ public: virtual nsapi_error_t init_module(); - ATHandler *_atHandlers; + virtual ATHandler *get_at_handler(FileHandle *fh); - ATHandler *get_at_handler(FileHandle *fh); + virtual ATHandler *get_at_handler(); /** Releases the given at_handler. If last reference to at_hander then it's deleted. * * @param at_handler + * @return NSAPI_ERROR_OK on success, NSAPI_ERROR_PARAMETER on failure */ - void release_at_handler(ATHandler *at_handler); + virtual nsapi_error_t release_at_handler(ATHandler *at_handler); /** Creates new instance of AT_CellularContext or if overridden, modem specific implementation. *