Skip to content

Commit dbdbae3

Browse files
author
Teemu Kultala
committed
cellular: AT Handler API
1 parent 3b138fb commit dbdbae3

File tree

11 files changed

+290
-70
lines changed

11 files changed

+290
-70
lines changed

UNITTESTS/features/cellular/framework/AT/at_cellulardevice/at_cellulardevicetest.cpp

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,16 @@ TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_get_at_handler)
6161
EXPECT_TRUE(dev.open_power(&fh1));
6262

6363
ATHandler_stub::fh_value = NULL;
64+
65+
AT_CellularDevice *dev2 = new AT_CellularDevice(&fh1);
66+
EXPECT_TRUE(dev2->open_information(&fh1));
67+
ATHandler *at = dev2->get_at_handler();
68+
EXPECT_TRUE(at->get_ref_count() == 4);
69+
delete dev2;
70+
EXPECT_TRUE(at->get_ref_count() == 3);
71+
AT_CellularDevice dev3(&fh1);
72+
EXPECT_TRUE(dev3.release_at_handler(at) == NSAPI_ERROR_OK);
73+
EXPECT_TRUE(ATHandler_stub::ref_count == 2);
6474
}
6575

6676
TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_open_network)
@@ -211,7 +221,7 @@ TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_close_information)
211221
AT_CellularBase_stub::handler_value = AT_CellularBase_stub::handler_at_constructor_value;
212222

213223
dev.close_information();
214-
EXPECT_TRUE(ATHandler_stub::ref_count == 1);
224+
EXPECT_TRUE(ATHandler_stub::ref_count == kATHandler_destructor_ref_ount);
215225

216226
ATHandler_stub::fh_value = NULL;
217227
}
@@ -276,13 +286,21 @@ TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_create_delete_context)
276286
FileHandle_stub fh1;
277287
AT_CellularDevice *dev = new AT_CellularDevice(&fh1);
278288

289+
ATHandler *at = dev->get_at_handler();
290+
EXPECT_TRUE(at->get_ref_count() == 1);
291+
EXPECT_TRUE(dev->release_at_handler(at) == NSAPI_ERROR_OK);
292+
279293
CellularContext *ctx = dev->create_context(NULL);
280294
delete dev;
281295

282296
dev = new AT_CellularDevice(&fh1);
297+
at = dev->get_at_handler();
298+
EXPECT_TRUE(at->get_ref_count() == 1);
283299
ctx = dev->create_context(NULL);
284300
CellularContext *ctx1 = dev->create_context(&fh1);
301+
EXPECT_TRUE(at->get_ref_count() == 3);
285302
CellularContext *ctx2 = dev->create_context(&fh1);
303+
EXPECT_TRUE(at->get_ref_count() == 4);
286304

287305
EXPECT_TRUE(ctx);
288306
EXPECT_TRUE(ctx1);
@@ -293,13 +311,21 @@ TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_create_delete_context)
293311
EXPECT_TRUE(xx);
294312

295313
dev->delete_context(ctx);
314+
EXPECT_TRUE(at->get_ref_count() == 3);
296315
dev->delete_context(ctx1);
316+
EXPECT_TRUE(at->get_ref_count() == 2);
297317
dev->delete_context(NULL);
318+
EXPECT_TRUE(at->get_ref_count() == 2);
298319
dev->delete_context(ctx2);
320+
EXPECT_TRUE(at->get_ref_count() == 1);
299321

300322
ctx = dev->create_context(NULL);
323+
EXPECT_TRUE(at->get_ref_count() == 2);
301324
ctx1 = dev->create_context(&fh1);
325+
EXPECT_TRUE(at->get_ref_count() == 3);
302326
ctx2 = dev->create_context(&fh1);
327+
EXPECT_TRUE(at->get_ref_count() == 4);
328+
EXPECT_TRUE(dev->release_at_handler(at) == NSAPI_ERROR_OK);
303329
EXPECT_TRUE(ctx);
304330
EXPECT_TRUE(ctx1);
305331
EXPECT_TRUE(ctx1 != ctx);

UNITTESTS/features/cellular/framework/AT/athandler/athandlertest.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,25 @@ TEST_F(TestATHandler, test_ATHandler_set_file_handle)
8686
at.set_file_handle(&fh2);
8787
}
8888

89+
TEST_F(TestATHandler, test_ATHandler_get_release)
90+
{
91+
EventQueue que;
92+
FileHandle_stub fh1;
93+
94+
ATHandler *at1 = ATHandler::get(&fh1, que, 0, ",", 0, 0);
95+
EXPECT_TRUE(at1->get_ref_count() == 1);
96+
EXPECT_TRUE(ATHandler::get(NULL, que, 0, ",", 0, 0) == NULL);
97+
98+
ATHandler *at2 = ATHandler::get(&fh1, que, 0, ",", 0, 0);
99+
EXPECT_TRUE(at1->get_ref_count() == 2);
100+
EXPECT_TRUE(at2->get_ref_count() == 2);
101+
102+
EXPECT_TRUE(ATHandler::release(at1) == NSAPI_ERROR_OK);
103+
EXPECT_TRUE(at2->get_ref_count() == 1);
104+
EXPECT_TRUE(ATHandler::release(at2) == NSAPI_ERROR_OK);
105+
EXPECT_TRUE(ATHandler::release(NULL) == NSAPI_ERROR_PARAMETER);
106+
}
107+
89108
TEST_F(TestATHandler, test_ATHandler_lock)
90109
{
91110
EventQueue que;

UNITTESTS/stubs/ATHandler_stub.cpp

Lines changed: 73 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ char *ATHandler_stub::urc_string_table[kATHandler_urc_table_max_size];
6060
ATHandler::ATHandler(FileHandle *fh, EventQueue &queue, int timeout, const char *output_delimiter, uint16_t send_delay) :
6161
_nextATHandler(0),
6262
_fileHandle(fh),
63-
_queue(queue)
63+
_queue(queue),
64+
_ref_count(1)
6465
{
6566
ATHandler_stub::ref_count = 1;
6667

@@ -72,6 +73,8 @@ ATHandler::ATHandler(FileHandle *fh, EventQueue &queue, int timeout, const char
7273
ATHandler_stub::urc_string_table[i++] = NULL;
7374
}
7475
}
76+
ATHandler *ATHandler::_atHandlers = NULL;
77+
PlatformMutex ATHandler::_getReleaseMutex;
7578

7679
void ATHandler::set_debug(bool debug_on)
7780
{
@@ -95,28 +98,93 @@ ATHandler::~ATHandler()
9598

9699
void ATHandler::inc_ref_count()
97100
{
98-
ATHandler_stub::ref_count++;
101+
_ref_count++;
102+
ATHandler_stub::ref_count = _ref_count;
99103
}
100104

101105
void ATHandler::dec_ref_count()
102106
{
103-
ATHandler_stub::ref_count--;
107+
_ref_count--;
108+
ATHandler_stub::ref_count = _ref_count;
104109
}
105110

106111
int ATHandler::get_ref_count()
107112
{
108-
return ATHandler_stub::ref_count;
113+
return _ref_count;
109114
}
110115

111116
FileHandle *ATHandler::get_file_handle()
112117
{
113-
return ATHandler_stub::fh_value;
118+
ATHandler_stub::fh_value = (FileHandle_stub *)_fileHandle;
119+
return _fileHandle;
114120
}
115121

116122
void ATHandler::set_file_handle(FileHandle *fh)
117123
{
118124
}
119125

126+
// each parser is associated with one filehandle (that is UART)
127+
ATHandler *ATHandler::get(FileHandle *fileHandle, events::EventQueue &queue, uint32_t timeout,
128+
const char *delimiter, uint16_t send_delay, bool debug_on)
129+
{
130+
if (!fileHandle) {
131+
return NULL;
132+
}
133+
134+
_getReleaseMutex.lock();
135+
ATHandler *atHandler = _atHandlers;
136+
while (atHandler) {
137+
if (atHandler->get_file_handle() == fileHandle) {
138+
atHandler->inc_ref_count();
139+
_getReleaseMutex.unlock();
140+
return atHandler;
141+
}
142+
atHandler = atHandler->_nextATHandler;
143+
}
144+
145+
atHandler = new ATHandler(fileHandle, queue, timeout, delimiter, send_delay);
146+
if (debug_on) {
147+
atHandler->set_debug(debug_on);
148+
}
149+
atHandler->_nextATHandler = _atHandlers;
150+
_atHandlers = atHandler;
151+
152+
_getReleaseMutex.unlock();
153+
return atHandler;
154+
}
155+
156+
nsapi_error_t ATHandler::release(ATHandler *at_handler)
157+
{
158+
if (!at_handler || at_handler->get_ref_count() == 0) {
159+
return NSAPI_ERROR_PARAMETER;
160+
}
161+
162+
_getReleaseMutex.lock();
163+
at_handler->dec_ref_count();
164+
if (at_handler->get_ref_count() == 0) {
165+
// we can delete this at_handler
166+
ATHandler *atHandler = _atHandlers;
167+
ATHandler *prev = NULL;
168+
while (atHandler) {
169+
if (atHandler == at_handler) {
170+
if (prev == NULL) {
171+
_atHandlers = _atHandlers->_nextATHandler;
172+
} else {
173+
prev->_nextATHandler = atHandler->_nextATHandler;
174+
}
175+
delete atHandler;
176+
at_handler = NULL;
177+
break;
178+
} else {
179+
prev = atHandler;
180+
atHandler = atHandler->_nextATHandler;
181+
}
182+
}
183+
}
184+
_getReleaseMutex.unlock();
185+
return NSAPI_ERROR_OK;
186+
}
187+
120188
nsapi_error_t ATHandler::set_urc_handler(const char *urc, mbed::Callback<void()> cb)
121189
{
122190
if (ATHandler_stub::urc_amount < kATHandler_urc_table_max_size) {

UNITTESTS/stubs/AT_CellularBase_stub.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ AT_CellularBase::AT_CellularBase(ATHandler &at) : _at(at)
3434

3535
ATHandler &AT_CellularBase::get_at_handler()
3636
{
37-
return *AT_CellularBase_stub::handler_value;
37+
AT_CellularBase_stub::handler_value = &_at;
38+
return _at;
3839
}
3940

4041
device_err_t AT_CellularBase::get_device_error() const

UNITTESTS/stubs/AT_CellularDevice_stub.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,22 +27,25 @@ AT_CellularDevice::AT_CellularDevice(FileHandle *fh) : CellularDevice(fh), _netw
2727
_sim(0), _power(0), _information(0), _context_list(0), _default_timeout(DEFAULT_AT_TIMEOUT),
2828
_modem_debug_on(false)
2929
{
30-
_atHandlers = new ATHandler(fh, _queue, 0, ",");
3130
}
3231

3332
AT_CellularDevice::~AT_CellularDevice()
3433
{
35-
delete _atHandlers;
3634
}
3735

3836
ATHandler *AT_CellularDevice::get_at_handler(FileHandle *fileHandle)
3937
{
40-
return _atHandlers;
38+
return ATHandler::get(fileHandle, _queue, _default_timeout, "\r", get_send_delay(), _modem_debug_on);
4139
}
4240

43-
void AT_CellularDevice::release_at_handler(ATHandler *at_handler)
41+
ATHandler *AT_CellularDevice::get_at_handler()
4442
{
43+
return get_at_handler(NULL);
44+
}
4545

46+
nsapi_error_t AT_CellularDevice::release_at_handler(ATHandler *at_handler)
47+
{
48+
return ATHandler::release(at_handler);
4649
}
4750

4851
CellularContext *create_context(FileHandle *fh = NULL, const char *apn = MBED_CONF_NSAPI_DEFAULT_CELLULAR_APN)
@@ -57,7 +60,7 @@ void delete_context(CellularContext *context)
5760

5861
CellularNetwork *AT_CellularDevice::open_network(FileHandle *fh)
5962
{
60-
return new AT_CellularNetwork(*_atHandlers);
63+
return new AT_CellularNetwork(*ATHandler::get(fh, _queue, _default_timeout, "\r", get_send_delay(), _modem_debug_on));
6164
}
6265

6366
CellularSMS *AT_CellularDevice::open_sms(FileHandle *fh)

UNITTESTS/target_h/myCellularDevice.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,14 @@ class myCellularDevice : public CellularDevice {
119119
{
120120
CellularDevice::cellular_callback(ev, ptr);
121121
}
122+
virtual ATHandler *get_at_handler()
123+
{
124+
return NULL;
125+
}
126+
virtual nsapi_error_t release_at_handler(ATHandler *at_handler)
127+
{
128+
return NSAPI_ERROR_OK;
129+
}
122130
AT_CellularNetwork *_network;
123131
AT_CellularContext *_context_list;
124132
};

features/cellular/framework/API/CellularDevice.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "CellularTargets.h"
2222
#include "CellularStateMachine.h"
2323
#include "Callback.h"
24+
#include "ATHandler.h"
2425

2526
namespace mbed {
2627

@@ -249,6 +250,20 @@ class CellularDevice {
249250
*/
250251
virtual CellularContext *get_context_list() const;
251252

253+
/** Get the current ATHandler instance in use for debug purposes etc.
254+
* Once use has been finished call to release_at_handler() has to be made
255+
*
256+
* @return Pointer to the ATHandler in use
257+
*/
258+
virtual ATHandler *get_at_handler() = 0;
259+
260+
/** Release the ATHandler taken into use with get_at_handler()
261+
*
262+
* @param at_handler
263+
* @return NSAPI_ERROR_OK on success, NSAPI_ERROR_PARAMETER on failure
264+
*/
265+
virtual nsapi_error_t release_at_handler(ATHandler *at_handler) = 0;
266+
252267
protected:
253268
friend class AT_CellularNetwork;
254269
friend class AT_CellularContext;

features/cellular/framework/AT/ATHandler.cpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ ATHandler::ATHandler(FileHandle *fh, EventQueue &queue, int timeout, const char
110110

111111
set_file_handle(fh);
112112
}
113+
ATHandler *ATHandler::_atHandlers = NULL;
114+
PlatformMutex ATHandler::_getReleaseMutex;
113115

114116
void ATHandler::set_debug(bool debug_on)
115117
{
@@ -160,6 +162,69 @@ void ATHandler::set_is_filehandle_usable(bool usable)
160162
_is_fh_usable = usable;
161163
}
162164

165+
166+
// each parser is associated with one filehandle (that is UART)
167+
ATHandler *ATHandler::get(FileHandle *fileHandle, events::EventQueue &queue, uint32_t timeout,
168+
const char *delimiter, uint16_t send_delay, bool debug_on)
169+
{
170+
if (!fileHandle) {
171+
return NULL;
172+
}
173+
174+
_getReleaseMutex.lock();
175+
ATHandler *atHandler = _atHandlers;
176+
while (atHandler) {
177+
if (atHandler->get_file_handle() == fileHandle) {
178+
atHandler->inc_ref_count();
179+
_getReleaseMutex.unlock();
180+
return atHandler;
181+
}
182+
atHandler = atHandler->_nextATHandler;
183+
}
184+
185+
atHandler = new ATHandler(fileHandle, queue, timeout, delimiter, send_delay);
186+
if (debug_on) {
187+
atHandler->set_debug(debug_on);
188+
}
189+
atHandler->_nextATHandler = _atHandlers;
190+
_atHandlers = atHandler;
191+
192+
_getReleaseMutex.unlock();
193+
return atHandler;
194+
}
195+
196+
nsapi_error_t ATHandler::release(ATHandler *at_handler)
197+
{
198+
if (!at_handler || at_handler->get_ref_count() == 0) {
199+
return NSAPI_ERROR_PARAMETER;
200+
}
201+
202+
_getReleaseMutex.lock();
203+
at_handler->dec_ref_count();
204+
if (at_handler->get_ref_count() == 0) {
205+
// we can delete this at_handler
206+
ATHandler *atHandler = _atHandlers;
207+
ATHandler *prev = NULL;
208+
while (atHandler) {
209+
if (atHandler == at_handler) {
210+
if (prev == NULL) {
211+
_atHandlers = _atHandlers->_nextATHandler;
212+
} else {
213+
prev->_nextATHandler = atHandler->_nextATHandler;
214+
}
215+
delete atHandler;
216+
at_handler = NULL;
217+
break;
218+
} else {
219+
prev = atHandler;
220+
atHandler = atHandler->_nextATHandler;
221+
}
222+
}
223+
}
224+
_getReleaseMutex.unlock();
225+
return NSAPI_ERROR_OK;
226+
}
227+
163228
nsapi_error_t ATHandler::set_urc_handler(const char *prefix, mbed::Callback<void()> callback)
164229
{
165230
if (find_urc_handler(prefix)) {

0 commit comments

Comments
 (0)