mirror of https://github.com/ARMmbed/mbed-os.git
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.pull/12065/head
parent
972d8a6107
commit
913cbd96a6
|
@ -24,6 +24,7 @@ set(unittest-test-sources
|
|||
stubs/AT_CellularDevice_stub.cpp
|
||||
stubs/AT_CellularStack_stub.cpp
|
||||
stubs/AT_CellularNetwork_stub.cpp
|
||||
stubs/AT_ControlPlane_netif_stub.cpp
|
||||
stubs/CellularDevice_stub.cpp
|
||||
stubs/CellularStateMachine_stub.cpp
|
||||
stubs/equeue_stub.c
|
||||
|
|
|
@ -198,6 +198,10 @@ bool AT_CellularContext::get_context()
|
|||
return true;
|
||||
}
|
||||
|
||||
const char* AT_CellularContext::get_nonip_context_type_str() {
|
||||
return "Non-IP";
|
||||
}
|
||||
|
||||
bool AT_CellularContext::set_new_context(int cid)
|
||||
{
|
||||
return true;
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (c) 2019, 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 "CellularUtil.h"
|
||||
#include "ThisThread.h"
|
||||
#include "AT_ControlPlane_netif.h"
|
||||
#include "CellularLog.h"
|
||||
|
||||
using namespace mbed_cellular_util;
|
||||
|
||||
namespace mbed {
|
||||
|
||||
AT_ControlPlane_netif::AT_ControlPlane_netif(ATHandler &at, int cid) : AT_CellularBase(at),
|
||||
_cid(cid), _cb(NULL), _data(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
AT_ControlPlane_netif::~AT_ControlPlane_netif()
|
||||
{}
|
||||
|
||||
void AT_ControlPlane_netif::urc_cp_recv()
|
||||
{
|
||||
}
|
||||
|
||||
nsapi_size_or_error_t AT_ControlPlane_netif::send(const void *cpdata, nsapi_size_t cpdata_length)
|
||||
{
|
||||
return cpdata_length;
|
||||
}
|
||||
|
||||
nsapi_size_or_error_t AT_ControlPlane_netif::recv(void *cpdata, nsapi_size_t cpdata_length)
|
||||
{
|
||||
return cpdata_length;
|
||||
}
|
||||
|
||||
void AT_ControlPlane_netif::attach(void (*callback)(void *), void *data)
|
||||
{
|
||||
}
|
||||
|
||||
void AT_ControlPlane_netif::data_received()
|
||||
{
|
||||
}
|
||||
|
||||
} //mbed namespace
|
|
@ -160,6 +160,10 @@ public:
|
|||
return true;
|
||||
};
|
||||
|
||||
const char* get_nonip_context_type_str() {
|
||||
return "Non-IP";
|
||||
}
|
||||
|
||||
bool set_new_context(int cid)
|
||||
{
|
||||
return true;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "AT_CellularContext.h"
|
||||
#include "AT_CellularNetwork.h"
|
||||
#include "AT_CellularStack.h"
|
||||
#include "AT_ControlPlane_netif.h"
|
||||
#include "AT_CellularDevice.h"
|
||||
#include "CellularLog.h"
|
||||
#if (DEVICE_SERIAL && DEVICE_INTERRUPTIN) || defined(DOXYGEN_ONLY)
|
||||
|
@ -322,6 +323,9 @@ void AT_CellularContext::set_credentials(const char *apn, const char *uname, con
|
|||
// PDP Context handling
|
||||
void AT_CellularContext::delete_current_context()
|
||||
{
|
||||
if (_cid <= 0) {
|
||||
return;
|
||||
}
|
||||
tr_info("Delete context %d", _cid);
|
||||
_at.clear_error();
|
||||
|
||||
|
@ -426,13 +430,17 @@ bool AT_CellularContext::get_context()
|
|||
return true;
|
||||
}
|
||||
|
||||
const char* AT_CellularContext::get_nonip_context_type_str() {
|
||||
return "Non-IP";
|
||||
}
|
||||
|
||||
bool AT_CellularContext::set_new_context(int cid)
|
||||
{
|
||||
char pdp_type_str[8 + 1] = {0};
|
||||
pdp_type_t pdp_type = IPV4_PDP_TYPE;
|
||||
|
||||
if (_nonip_req && _cp_in_use && get_device()->get_property(AT_CellularDevice::PROPERTY_NON_IP_PDP_TYPE)) {
|
||||
strncpy(pdp_type_str, "Non-IP", sizeof(pdp_type_str));
|
||||
strncpy(pdp_type_str, get_nonip_context_type_str(), sizeof(pdp_type_str));
|
||||
pdp_type = NON_IP_PDP_TYPE;
|
||||
} else if (get_device()->get_property(AT_CellularDevice::PROPERTY_IPV4V6_PDP_TYPE) ||
|
||||
(get_device()->get_property(AT_CellularDevice::PROPERTY_IPV4_PDP_TYPE) &&
|
||||
|
@ -556,7 +564,7 @@ nsapi_error_t AT_CellularContext::find_and_activate_context()
|
|||
}
|
||||
|
||||
// do check for stack to validate that we have support for stack
|
||||
if (!get_stack()) {
|
||||
if (!(_nonip_req && _cp_in_use) && !get_stack()) {
|
||||
_at.unlock();
|
||||
tr_error("No cellular stack!");
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
|
@ -962,6 +970,7 @@ void AT_CellularContext::cellular_callback(nsapi_event_t ev, intptr_t ptr)
|
|||
_nw = _device->open_network(_fh);
|
||||
}
|
||||
|
||||
#if MBED_CONF_CELLULAR_CONTROL_PLANE_OPT
|
||||
if (_cp_req && !_cp_in_use && (_cb_data.error == NSAPI_ERROR_OK) &&
|
||||
(st == CellularSIMStatusChanged && data->status_data == CellularDevice::SimStateReady)) {
|
||||
if (setup_control_plane_opt() != NSAPI_ERROR_OK) {
|
||||
|
@ -970,6 +979,7 @@ void AT_CellularContext::cellular_callback(nsapi_event_t ev, intptr_t ptr)
|
|||
tr_info("Control plane SETUP success!");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (_is_blocking) {
|
||||
if (_cb_data.error != NSAPI_ERROR_OK) {
|
||||
|
@ -1044,8 +1054,10 @@ void AT_CellularContext::cellular_callback(nsapi_event_t ev, intptr_t ptr)
|
|||
|
||||
ControlPlane_netif *AT_CellularContext::get_cp_netif()
|
||||
{
|
||||
tr_error("No control plane interface available from base context!");
|
||||
return NULL;
|
||||
if (!_cp_netif) {
|
||||
_cp_netif = new AT_ControlPlane_netif(_at, _cid);
|
||||
}
|
||||
return _cp_netif;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularContext::setup_control_plane_opt()
|
||||
|
@ -1068,19 +1080,11 @@ nsapi_error_t AT_CellularContext::setup_control_plane_opt()
|
|||
ciot_opt_ret = _nw->set_ciot_optimization_config(mbed::CellularNetwork::CIOT_OPT_CONTROL_PLANE,
|
||||
mbed::CellularNetwork::PREFERRED_UE_OPT_CONTROL_PLANE,
|
||||
callback(this, &AT_CellularContext::ciot_opt_cb));
|
||||
|
||||
if (ciot_opt_ret != NSAPI_ERROR_OK) {
|
||||
return ciot_opt_ret;
|
||||
if (ciot_opt_ret == NSAPI_ERROR_OK) {
|
||||
// assume network supports CIoT optimizations until ciot_opt_cb
|
||||
_cp_in_use = true;
|
||||
}
|
||||
|
||||
//wait for control plane opt call back to release semaphore
|
||||
_cp_opt_semaphore.try_acquire_for(CP_OPT_NW_REPLY_TIMEOUT);
|
||||
|
||||
if (_cp_in_use) {
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
return NSAPI_ERROR_DEVICE_ERROR;
|
||||
return ciot_opt_ret;
|
||||
}
|
||||
|
||||
void AT_CellularContext::ciot_opt_cb(mbed::CellularNetwork::CIoT_Supported_Opt ciot_opt)
|
||||
|
@ -1088,15 +1092,18 @@ void AT_CellularContext::ciot_opt_cb(mbed::CellularNetwork::CIoT_Supported_Opt
|
|||
if (ciot_opt == mbed::CellularNetwork::CIOT_OPT_CONTROL_PLANE ||
|
||||
ciot_opt == mbed::CellularNetwork::CIOT_OPT_BOTH) {
|
||||
_cp_in_use = true;
|
||||
} else {
|
||||
_cp_in_use = false;
|
||||
}
|
||||
_cp_opt_semaphore.release();
|
||||
}
|
||||
|
||||
void AT_CellularContext::set_disconnect()
|
||||
{
|
||||
tr_debug("AT_CellularContext::set_disconnect()");
|
||||
_is_connected = false;
|
||||
_device->cellular_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_DISCONNECTED, this);
|
||||
if (_is_connected) {
|
||||
_is_connected = false;
|
||||
_device->cellular_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_DISCONNECTED, this);
|
||||
}
|
||||
}
|
||||
|
||||
void AT_CellularContext::set_cid(int cid)
|
||||
|
|
|
@ -108,6 +108,10 @@ protected:
|
|||
virtual bool get_context();
|
||||
AT_CellularDevice::CellularProperty pdp_type_t_to_cellular_property(pdp_type_t pdp_type);
|
||||
bool set_new_context(int cid);
|
||||
/** Get string name for NIDD context type.
|
||||
* @return NIDD context text, e.g. Non-IP or NONIP
|
||||
*/
|
||||
virtual const char* get_nonip_context_type_str();
|
||||
|
||||
private:
|
||||
#if NSAPI_PPP_AVAILABLE
|
||||
|
|
|
@ -375,7 +375,11 @@ nsapi_error_t AT_CellularNetwork::set_ciot_optimization_config(CIoT_Supported_Op
|
|||
Callback<void(CIoT_Supported_Opt)> network_support_cb)
|
||||
{
|
||||
_ciotopt_network_support_cb = network_support_cb;
|
||||
return _at.at_cmd_discard("+CCIOTOPT", "=1,", "%d%d", supported_opt, preferred_opt);
|
||||
nsapi_error_t err = _at.at_cmd_discard("+CRTDCP", "=", "%d", 1);
|
||||
if (!err) {
|
||||
err = _at.at_cmd_discard("+CCIOTOPT", "=1,", "%d%d", supported_opt, preferred_opt);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
void AT_CellularNetwork::urc_cciotopti()
|
||||
|
@ -690,7 +694,7 @@ nsapi_error_t AT_CellularNetwork::clear()
|
|||
}
|
||||
context = context->next;
|
||||
}
|
||||
#ifdef MBED_CONF_NSAPI_DEFAULT_CELLULAR_APN
|
||||
#if defined(MBED_CONF_NSAPI_DEFAULT_CELLULAR_APN) && !MBED_CONF_CELLULAR_CONTROL_PLANE_OPT
|
||||
char pdp_type_str[sizeof("IPV4V6")];
|
||||
if (_device.get_property(AT_CellularDevice::PROPERTY_IPV4V6_PDP_TYPE) ||
|
||||
(_device.get_property(AT_CellularDevice::PROPERTY_IPV4_PDP_TYPE) && _device.get_property(AT_CellularDevice::PROPERTY_IPV6_PDP_TYPE))) {
|
||||
|
|
|
@ -117,7 +117,7 @@ protected:
|
|||
*
|
||||
* @return NSAPI_ERROR_OK on success
|
||||
*/
|
||||
nsapi_error_t clear();
|
||||
virtual nsapi_error_t clear();
|
||||
|
||||
private:
|
||||
void urc_creg();
|
||||
|
|
|
@ -1,10 +1,31 @@
|
|||
/*AT_ControlPlane_netif.cpp*/
|
||||
/*
|
||||
* Copyright (c) 2019, 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 "CellularUtil.h"
|
||||
#include "ThisThread.h"
|
||||
#include "AT_ControlPlane_netif.h"
|
||||
#include "CellularLog.h"
|
||||
|
||||
using namespace mbed_cellular_util;
|
||||
|
||||
namespace mbed {
|
||||
|
||||
AT_ControlPlane_netif::AT_ControlPlane_netif(ATHandler &at, int cid) :
|
||||
_cid(cid), _cb(NULL), _data(NULL), _recv_len(0), _at(at)
|
||||
_cid(cid), _cb(NULL), _data(NULL), _at(at)
|
||||
{
|
||||
_at.set_urc_handler("+CRTDCP:", mbed::Callback<void()>(this, &AT_ControlPlane_netif::urc_cp_recv));
|
||||
}
|
||||
|
@ -18,44 +39,58 @@ void AT_ControlPlane_netif::urc_cp_recv()
|
|||
_at.lock();
|
||||
int cid = _at.read_int();
|
||||
int cpdata_length = _at.read_int();
|
||||
int read_len = _at.read_string(_recv_buffer, sizeof(_recv_buffer));
|
||||
|
||||
_at.unlock();
|
||||
if (cpdata_length < 0) {
|
||||
return;
|
||||
}
|
||||
uint8_t *cpdata = new uint8_t[cpdata_length];
|
||||
ssize_t read_len = _at.read_hex_string((char *)cpdata, cpdata_length);
|
||||
|
||||
// cid not expected to be different because: one context - one file handle
|
||||
// so this file handle cannot get urc from different context
|
||||
if (read_len > 0 && read_len == cpdata_length && cid == _cid) {
|
||||
_recv_len = read_len;
|
||||
packet_t *packet = _packet_list.add_new();
|
||||
packet->data = cpdata;
|
||||
packet->data_len = cpdata_length;
|
||||
data_received();
|
||||
} else {
|
||||
delete[] cpdata;
|
||||
}
|
||||
_at.unlock();
|
||||
}
|
||||
|
||||
nsapi_size_or_error_t AT_ControlPlane_netif::send(const void *cpdata, nsapi_size_t cpdata_length)
|
||||
{
|
||||
//CSODCP
|
||||
if (cpdata_length > MAX_CP_DATA_RECV_LEN) {
|
||||
return NSAPI_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
_at.lock();
|
||||
_at.cmd_start("AT+CSODCP=");
|
||||
_at.write_int(_cid);
|
||||
_at.write_int(cpdata_length);
|
||||
_at.write_hex_string((char *)cpdata, cpdata_length);
|
||||
_at.cmd_stop_read_resp();
|
||||
nsapi_size_or_error_t err = _at.unlock_return_error();
|
||||
|
||||
nsapi_size_or_error_t err = _at.at_cmd_discard("+CSODCP", "=", "%d%d%b", _cid, cpdata_length, cpdata, cpdata_length);
|
||||
|
||||
return (err == NSAPI_ERROR_OK) ? cpdata_length : err;
|
||||
return err ? err : cpdata_length;
|
||||
}
|
||||
|
||||
nsapi_size_or_error_t AT_ControlPlane_netif::recv(void *cpdata, nsapi_size_t cpdata_length)
|
||||
{
|
||||
// If no data received through CRTDCP URC
|
||||
if (!_recv_len) {
|
||||
return NSAPI_ERROR_WOULD_BLOCK;
|
||||
_at.lock();
|
||||
if (_packet_list.count() <= 0) {
|
||||
(void) send("", 0); // poll for missing +CRTDCP indications
|
||||
if (_packet_list.count() <= 0) {
|
||||
return NSAPI_ERROR_WOULD_BLOCK;
|
||||
}
|
||||
}
|
||||
|
||||
// If too small buffer for data
|
||||
if (_recv_len > cpdata_length) {
|
||||
return NSAPI_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
memcpy(cpdata, _recv_buffer, _recv_len);
|
||||
size_t recv = _recv_len;
|
||||
_recv_len = 0;
|
||||
return recv;
|
||||
packet_t *packet = _packet_list.dequeue();
|
||||
int data_len = (cpdata_length >= packet->data_len) ? packet->data_len : cpdata_length;
|
||||
memcpy(cpdata, packet->data, data_len);
|
||||
delete[] packet->data;
|
||||
delete (packet);
|
||||
_at.unlock();
|
||||
return data_len;
|
||||
}
|
||||
|
||||
void AT_ControlPlane_netif::attach(void (*callback)(void *), void *data)
|
||||
|
|
|
@ -1,3 +1,21 @@
|
|||
/*
|
||||
* Copyright (c) 2019, 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 "CellularList.h"
|
||||
#include "ControlPlane_netif.h"
|
||||
#include "ATHandler.h"
|
||||
|
||||
|
@ -28,10 +46,14 @@ protected:
|
|||
int _cid;
|
||||
|
||||
private:
|
||||
struct packet_t {
|
||||
uint8_t *data;
|
||||
nsapi_size_t data_len;
|
||||
packet_t *next;
|
||||
};
|
||||
CellularList<packet_t> _packet_list;
|
||||
void (*_cb)(void *);
|
||||
void *_data;
|
||||
char _recv_buffer[MBED_CONF_CELLULAR_MAX_CP_DATA_RECV_LEN];
|
||||
size_t _recv_len;
|
||||
// Called on receiving URC: +CRTDCP
|
||||
void urc_cp_recv();
|
||||
|
||||
|
|
|
@ -378,6 +378,8 @@ pdp_type_t string_to_pdp_type(const char *pdp_type_str)
|
|||
pdp_type = IPV4_PDP_TYPE;
|
||||
} else if (len == 6 && memcmp(pdp_type_str, "Non-IP", len) == 0) {
|
||||
pdp_type = NON_IP_PDP_TYPE;
|
||||
} else if (len == 5 && memcmp(pdp_type_str, "NONIP", len) == 0) {
|
||||
pdp_type = NON_IP_PDP_TYPE;
|
||||
}
|
||||
return pdp_type;
|
||||
}
|
||||
|
|
|
@ -69,6 +69,10 @@ CellularContext::CellularContext() : _next(0), _stack(0), _pdp_type(DEFAULT_PDP_
|
|||
|
||||
void CellularContext::cp_data_received()
|
||||
{
|
||||
if (!_cp_netif) {
|
||||
tr_warn("Cellular Non-IP callback missing");
|
||||
return;
|
||||
}
|
||||
_cp_netif->data_received();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue