Skip to content

Commit 19342e2

Browse files
author
Ari Parkkila
committed
Cellular: Change 3GPP TS 27.007 NIDD to async
Add a missing license header. Remove semaphores and add +CRTDCP to support async operation. Fix delete context and disconnect to execute just once. Add support for NONIP PPD type. Change CellularNetwork::clear() to virtual so it can be overridden.
1 parent 1dc53e4 commit 19342e2

File tree

12 files changed

+191
-47
lines changed

12 files changed

+191
-47
lines changed

UNITTESTS/features/cellular/framework/AT/at_cellularcontext/unittest.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ set(unittest-test-sources
2424
stubs/AT_CellularDevice_stub.cpp
2525
stubs/AT_CellularStack_stub.cpp
2626
stubs/AT_CellularNetwork_stub.cpp
27+
stubs/AT_ControlPlane_netif_stub.cpp
2728
stubs/CellularDevice_stub.cpp
2829
stubs/CellularStateMachine_stub.cpp
2930
stubs/equeue_stub.c

UNITTESTS/stubs/AT_CellularContext_stub.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,10 @@ bool AT_CellularContext::get_context()
198198
return true;
199199
}
200200

201+
const char* AT_CellularContext::get_nonip_context_type_str() {
202+
return "Non-IP";
203+
}
204+
201205
bool AT_CellularContext::set_new_context(int cid)
202206
{
203207
return true;
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright (c) 2019, Arm Limited and affiliates.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
#include "CellularUtil.h"
19+
#include "ThisThread.h"
20+
#include "AT_ControlPlane_netif.h"
21+
#include "CellularLog.h"
22+
23+
using namespace mbed_cellular_util;
24+
25+
namespace mbed {
26+
27+
AT_ControlPlane_netif::AT_ControlPlane_netif(ATHandler &at, int cid) : AT_CellularBase(at),
28+
_cid(cid), _cb(NULL), _data(NULL)
29+
{
30+
}
31+
32+
AT_ControlPlane_netif::~AT_ControlPlane_netif()
33+
{}
34+
35+
void AT_ControlPlane_netif::urc_cp_recv()
36+
{
37+
}
38+
39+
nsapi_size_or_error_t AT_ControlPlane_netif::send(const void *cpdata, nsapi_size_t cpdata_length)
40+
{
41+
return cpdata_length;
42+
}
43+
44+
nsapi_size_or_error_t AT_ControlPlane_netif::recv(void *cpdata, nsapi_size_t cpdata_length)
45+
{
46+
return cpdata_length;
47+
}
48+
49+
void AT_ControlPlane_netif::attach(void (*callback)(void *), void *data)
50+
{
51+
}
52+
53+
void AT_ControlPlane_netif::data_received()
54+
{
55+
}
56+
57+
} //mbed namespace

UNITTESTS/target_h/myCellularContext.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,10 @@ class myCellularContext : public CellularContext {
160160
return true;
161161
};
162162

163+
const char* get_nonip_context_type_str() {
164+
return "Non-IP";
165+
}
166+
163167
bool set_new_context(int cid)
164168
{
165169
return true;

features/cellular/framework/AT/AT_CellularContext.cpp

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "AT_CellularContext.h"
2020
#include "AT_CellularNetwork.h"
2121
#include "AT_CellularStack.h"
22+
#include "AT_ControlPlane_netif.h"
2223
#include "AT_CellularDevice.h"
2324
#include "CellularLog.h"
2425
#if (DEVICE_SERIAL && DEVICE_INTERRUPTIN) || defined(DOXYGEN_ONLY)
@@ -322,6 +323,9 @@ void AT_CellularContext::set_credentials(const char *apn, const char *uname, con
322323
// PDP Context handling
323324
void AT_CellularContext::delete_current_context()
324325
{
326+
if (_cid <= 0) {
327+
return;
328+
}
325329
tr_info("Delete context %d", _cid);
326330
_at.clear_error();
327331

@@ -426,13 +430,17 @@ bool AT_CellularContext::get_context()
426430
return true;
427431
}
428432

433+
const char* AT_CellularContext::get_nonip_context_type_str() {
434+
return "Non-IP";
435+
}
436+
429437
bool AT_CellularContext::set_new_context(int cid)
430438
{
431439
char pdp_type_str[8 + 1] = {0};
432440
pdp_type_t pdp_type = IPV4_PDP_TYPE;
433441

434442
if (_nonip_req && _cp_in_use && get_device()->get_property(AT_CellularDevice::PROPERTY_NON_IP_PDP_TYPE)) {
435-
strncpy(pdp_type_str, "Non-IP", sizeof(pdp_type_str));
443+
strncpy(pdp_type_str, get_nonip_context_type_str(), sizeof(pdp_type_str));
436444
pdp_type = NON_IP_PDP_TYPE;
437445
} else if (get_device()->get_property(AT_CellularDevice::PROPERTY_IPV4V6_PDP_TYPE) ||
438446
(get_device()->get_property(AT_CellularDevice::PROPERTY_IPV4_PDP_TYPE) &&
@@ -544,7 +552,7 @@ nsapi_error_t AT_CellularContext::find_and_activate_context()
544552
}
545553

546554
// do check for stack to validate that we have support for stack
547-
if (!get_stack()) {
555+
if (!(_nonip_req && _cp_in_use) && !get_stack()) {
548556
_at.unlock();
549557
tr_error("No cellular stack!");
550558
return NSAPI_ERROR_UNSUPPORTED;
@@ -950,6 +958,7 @@ void AT_CellularContext::cellular_callback(nsapi_event_t ev, intptr_t ptr)
950958
_nw = _device->open_network(_fh);
951959
}
952960

961+
#if MBED_CONF_CELLULAR_CONTROL_PLANE_OPT
953962
if (_cp_req && !_cp_in_use && (_cb_data.error == NSAPI_ERROR_OK) &&
954963
(st == CellularSIMStatusChanged && data->status_data == CellularDevice::SimStateReady)) {
955964
if (setup_control_plane_opt() != NSAPI_ERROR_OK) {
@@ -958,6 +967,7 @@ void AT_CellularContext::cellular_callback(nsapi_event_t ev, intptr_t ptr)
958967
tr_info("Control plane SETUP success!");
959968
}
960969
}
970+
#endif
961971

962972
if (_is_blocking) {
963973
if (_cb_data.error != NSAPI_ERROR_OK) {
@@ -1032,8 +1042,10 @@ void AT_CellularContext::cellular_callback(nsapi_event_t ev, intptr_t ptr)
10321042

10331043
ControlPlane_netif *AT_CellularContext::get_cp_netif()
10341044
{
1035-
tr_error("No control plane interface available from base context!");
1036-
return NULL;
1045+
if (!_cp_netif) {
1046+
_cp_netif = new AT_ControlPlane_netif(_at, _cid);
1047+
}
1048+
return _cp_netif;
10371049
}
10381050

10391051
nsapi_error_t AT_CellularContext::setup_control_plane_opt()
@@ -1056,35 +1068,30 @@ nsapi_error_t AT_CellularContext::setup_control_plane_opt()
10561068
ciot_opt_ret = _nw->set_ciot_optimization_config(mbed::CellularNetwork::CIOT_OPT_CONTROL_PLANE,
10571069
mbed::CellularNetwork::PREFERRED_UE_OPT_CONTROL_PLANE,
10581070
callback(this, &AT_CellularContext::ciot_opt_cb));
1059-
1060-
if (ciot_opt_ret != NSAPI_ERROR_OK) {
1061-
return ciot_opt_ret;
1062-
}
1063-
1064-
//wait for control plane opt call back to release semaphore
1065-
_cp_opt_semaphore.try_acquire_for(CP_OPT_NW_REPLY_TIMEOUT);
1066-
1067-
if (_cp_in_use) {
1068-
return NSAPI_ERROR_OK;
1071+
if (ciot_opt_ret == NSAPI_ERROR_OK) {
1072+
// assume network supports CIoT optimizations until ciot_opt_cb
1073+
_cp_in_use = true;
10691074
}
1070-
1071-
return NSAPI_ERROR_DEVICE_ERROR;
1075+
return ciot_opt_ret;
10721076
}
10731077

10741078
void AT_CellularContext::ciot_opt_cb(mbed::CellularNetwork::CIoT_Supported_Opt ciot_opt)
10751079
{
10761080
if (ciot_opt == mbed::CellularNetwork::CIOT_OPT_CONTROL_PLANE ||
10771081
ciot_opt == mbed::CellularNetwork::CIOT_OPT_BOTH) {
10781082
_cp_in_use = true;
1083+
} else {
1084+
_cp_in_use = false;
10791085
}
1080-
_cp_opt_semaphore.release();
10811086
}
10821087

10831088
void AT_CellularContext::set_disconnect()
10841089
{
10851090
tr_debug("AT_CellularContext::set_disconnect()");
1086-
_is_connected = false;
1087-
_device->cellular_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_DISCONNECTED, this);
1091+
if (_is_connected) {
1092+
_is_connected = false;
1093+
_device->cellular_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_DISCONNECTED, this);
1094+
}
10881095
}
10891096

10901097
void AT_CellularContext::set_cid(int cid)

features/cellular/framework/AT/AT_CellularContext.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,10 @@ class AT_CellularContext : public CellularContext {
107107
virtual bool get_context();
108108
AT_CellularDevice::CellularProperty pdp_type_t_to_cellular_property(pdp_type_t pdp_type);
109109
bool set_new_context(int cid);
110+
/** Get string name for NIDD context type.
111+
* @return NIDD context text, e.g. Non-IP or NONIP
112+
*/
113+
virtual const char* get_nonip_context_type_str();
110114
private:
111115
#if NSAPI_PPP_AVAILABLE
112116
nsapi_error_t open_data_channel();

features/cellular/framework/AT/AT_CellularNetwork.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,11 @@ nsapi_error_t AT_CellularNetwork::set_ciot_optimization_config(CIoT_Supported_Op
367367
Callback<void(CIoT_Supported_Opt)> network_support_cb)
368368
{
369369
_ciotopt_network_support_cb = network_support_cb;
370-
return _at.at_cmd_discard("+CCIOTOPT", "=1,", "%d%d", supported_opt, preferred_opt);
370+
nsapi_error_t err = _at.at_cmd_discard("+CRTDCP", "=", "%d", 1);
371+
if (!err) {
372+
err = _at.at_cmd_discard("+CCIOTOPT", "=1,", "%d%d", supported_opt, preferred_opt);
373+
}
374+
return err;
371375
}
372376

373377
void AT_CellularNetwork::urc_cciotopti()
@@ -682,7 +686,7 @@ nsapi_error_t AT_CellularNetwork::clear()
682686
}
683687
context = context->next;
684688
}
685-
#ifdef MBED_CONF_NSAPI_DEFAULT_CELLULAR_APN
689+
#if defined(MBED_CONF_NSAPI_DEFAULT_CELLULAR_APN) && !MBED_CONF_CELLULAR_CONTROL_PLANE_OPT
686690
char pdp_type_str[sizeof("IPV4V6")];
687691
if (_device.get_property(AT_CellularDevice::PROPERTY_IPV4V6_PDP_TYPE) ||
688692
(_device.get_property(AT_CellularDevice::PROPERTY_IPV4_PDP_TYPE) && _device.get_property(AT_CellularDevice::PROPERTY_IPV6_PDP_TYPE))) {

features/cellular/framework/AT/AT_CellularNetwork.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ class AT_CellularNetwork : public CellularNetwork {
119119
*
120120
* @return NSAPI_ERROR_OK on success
121121
*/
122-
nsapi_error_t clear();
122+
virtual nsapi_error_t clear();
123123

124124
private:
125125
void urc_creg();

features/cellular/framework/AT/AT_ControlPlane_netif.cpp

Lines changed: 58 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,31 @@
1-
/*AT_ControlPlane_netif.cpp*/
1+
/*
2+
* Copyright (c) 2019, Arm Limited and affiliates.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
#include "CellularUtil.h"
19+
#include "ThisThread.h"
220
#include "AT_ControlPlane_netif.h"
21+
#include "CellularLog.h"
22+
23+
using namespace mbed_cellular_util;
324

425
namespace mbed {
526

627
AT_ControlPlane_netif::AT_ControlPlane_netif(ATHandler &at, int cid) :
7-
_cid(cid), _cb(NULL), _data(NULL), _recv_len(0), _at(at)
28+
_cid(cid), _cb(NULL), _data(NULL), _at(at)
829
{
930
_at.set_urc_handler("+CRTDCP:", mbed::Callback<void()>(this, &AT_ControlPlane_netif::urc_cp_recv));
1031
}
@@ -18,44 +39,58 @@ void AT_ControlPlane_netif::urc_cp_recv()
1839
_at.lock();
1940
int cid = _at.read_int();
2041
int cpdata_length = _at.read_int();
21-
int read_len = _at.read_string(_recv_buffer, sizeof(_recv_buffer));
22-
23-
_at.unlock();
42+
if (cpdata_length < 0) {
43+
return;
44+
}
45+
uint8_t *cpdata = new uint8_t[cpdata_length];
46+
ssize_t read_len = _at.read_hex_string((char *)cpdata, cpdata_length);
2447

2548
// cid not expected to be different because: one context - one file handle
2649
// so this file handle cannot get urc from different context
2750
if (read_len > 0 && read_len == cpdata_length && cid == _cid) {
28-
_recv_len = read_len;
51+
packet_t *packet = _packet_list.add_new();
52+
packet->data = cpdata;
53+
packet->data_len = cpdata_length;
2954
data_received();
55+
} else {
56+
delete[] cpdata;
3057
}
58+
_at.unlock();
3159
}
3260

3361
nsapi_size_or_error_t AT_ControlPlane_netif::send(const void *cpdata, nsapi_size_t cpdata_length)
3462
{
35-
//CSODCP
36-
_at.lock();
63+
if (cpdata_length > MAX_CP_DATA_RECV_LEN) {
64+
return NSAPI_ERROR_PARAMETER;
65+
}
3766

38-
nsapi_size_or_error_t err = _at.at_cmd_discard("+CSODCP", "=", "%d%d%b", _cid, cpdata_length, cpdata, cpdata_length);
67+
_at.lock();
68+
_at.cmd_start("AT+CSODCP=");
69+
_at.write_int(_cid);
70+
_at.write_int(cpdata_length);
71+
_at.write_hex_string((char *)cpdata, cpdata_length);
72+
_at.cmd_stop_read_resp();
73+
nsapi_size_or_error_t err = _at.unlock_return_error();
3974

40-
return (err == NSAPI_ERROR_OK) ? cpdata_length : err;
75+
return err ? err : cpdata_length;
4176
}
4277

4378
nsapi_size_or_error_t AT_ControlPlane_netif::recv(void *cpdata, nsapi_size_t cpdata_length)
4479
{
45-
// If no data received through CRTDCP URC
46-
if (!_recv_len) {
47-
return NSAPI_ERROR_WOULD_BLOCK;
48-
}
49-
50-
// If too small buffer for data
51-
if (_recv_len > cpdata_length) {
52-
return NSAPI_ERROR_DEVICE_ERROR;
80+
_at.lock();
81+
if (_packet_list.count() <= 0) {
82+
(void) send("", 0); // poll for missing +CRTDCP indications
83+
if (_packet_list.count() <= 0) {
84+
return NSAPI_ERROR_WOULD_BLOCK;
85+
}
5386
}
54-
55-
memcpy(cpdata, _recv_buffer, _recv_len);
56-
size_t recv = _recv_len;
57-
_recv_len = 0;
58-
return recv;
87+
packet_t *packet = _packet_list.dequeue();
88+
int data_len = (cpdata_length >= packet->data_len) ? packet->data_len : cpdata_length;
89+
memcpy(cpdata, packet->data, data_len);
90+
delete[] packet->data;
91+
delete (packet);
92+
_at.unlock();
93+
return data_len;
5994
}
6095

6196
void AT_ControlPlane_netif::attach(void (*callback)(void *), void *data)

0 commit comments

Comments
 (0)