mirror of https://github.com/ARMmbed/mbed-os.git
Cellular: major refactoring while introducing new CellularContext class.
parent
8880538eba
commit
ad2abbe887
|
@ -146,7 +146,7 @@ nsapi_error_t CellularConnectionFSM::init()
|
|||
_state = STATE_INIT;
|
||||
_next_state = STATE_INIT;
|
||||
|
||||
return _network->init();
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
bool CellularConnectionFSM::power_on()
|
||||
|
@ -447,7 +447,7 @@ void CellularConnectionFSM::state_device_ready()
|
|||
}
|
||||
} else {
|
||||
if (_retry_count == 0) {
|
||||
(void)_power->set_device_ready_urc_cb(mbed::callback(this, &CellularConnectionFSM::ready_urc_cb));
|
||||
_power->set_device_ready_urc_cb(mbed::callback(this, &CellularConnectionFSM::ready_urc_cb));
|
||||
}
|
||||
retry_state_or_fail();
|
||||
}
|
||||
|
@ -528,26 +528,26 @@ void CellularConnectionFSM::state_activating_pdp_context()
|
|||
{
|
||||
_cellularDevice->set_timeout(TIMEOUT_CONNECT);
|
||||
tr_info("Activate PDP Context (timeout %d ms)", TIMEOUT_CONNECT);
|
||||
if (_network->activate_context() == NSAPI_ERROR_OK) {
|
||||
/* if (_network->activate_context() == NSAPI_ERROR_OK) {
|
||||
// when using modems stack connect is synchronous
|
||||
_next_state = STATE_CONNECTING_NETWORK;
|
||||
} else {
|
||||
retry_state_or_fail();
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
void CellularConnectionFSM::state_connect_to_network()
|
||||
{
|
||||
_cellularDevice->set_timeout(TIMEOUT_CONNECT);
|
||||
tr_info("Connect to cellular network (timeout %d ms)", TIMEOUT_CONNECT);
|
||||
if (_network->connect() == NSAPI_ERROR_OK) {
|
||||
/*if (_network->connect() == NSAPI_ERROR_OK) {
|
||||
_cellularDevice->set_timeout(TIMEOUT_NETWORK);
|
||||
tr_debug("Connected to cellular network, set at timeout (timeout %d ms)", TIMEOUT_NETWORK);
|
||||
// when using modems stack connect is synchronous
|
||||
_next_state = STATE_CONNECTED;
|
||||
} else {
|
||||
retry_state_or_fail();
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
void CellularConnectionFSM::state_connected()
|
||||
|
@ -719,11 +719,6 @@ CellularSIM *CellularConnectionFSM::get_sim()
|
|||
return _sim;
|
||||
}
|
||||
|
||||
NetworkStack *CellularConnectionFSM::get_stack()
|
||||
{
|
||||
return _cellularDevice->get_stack();
|
||||
}
|
||||
|
||||
void CellularConnectionFSM::set_retry_timeout_array(uint16_t timeout[], int array_len)
|
||||
{
|
||||
_retry_array_length = array_len > MAX_RETRY_ARRAY_SIZE ? MAX_RETRY_ARRAY_SIZE : array_len;
|
||||
|
|
|
@ -178,10 +178,6 @@ private:
|
|||
nsapi_error_t continue_from_state(CellularState state);
|
||||
bool is_registered_to_plmn();
|
||||
|
||||
private:
|
||||
friend class EasyCellularConnection;
|
||||
NetworkStack *get_stack();
|
||||
|
||||
private:
|
||||
void report_failure(const char *msg);
|
||||
void event();
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#endif
|
||||
|
||||
#include "EasyCellularConnection.h"
|
||||
#include "CellularContext.h"
|
||||
#include "CellularSIM.h"
|
||||
#include "CellularLog.h"
|
||||
#include "mbed_wait_api.h"
|
||||
|
@ -41,10 +42,10 @@ void EasyCellularConnection::network_callback(nsapi_event_t ev, intptr_t ptr)
|
|||
}
|
||||
}
|
||||
|
||||
EasyCellularConnection::EasyCellularConnection(CellularDevice *device) : _is_initialized(false),
|
||||
_serial(MDMTXD, MDMRXD, MBED_CONF_PLATFORM_DEFAULT_SERIAL_BAUD_RATE), _device(device),
|
||||
EasyCellularConnection::EasyCellularConnection(CellularContext *ctx) : _is_initialized(false), _context(ctx),
|
||||
_credentials_err(NSAPI_ERROR_OK), _status_cb(0)
|
||||
{
|
||||
_device = CellularDevice::get_default_instance();
|
||||
#if USE_APN_LOOKUP
|
||||
_credentials_set = false;
|
||||
#endif // #if USE_APN_LOOKUP
|
||||
|
@ -52,29 +53,17 @@ EasyCellularConnection::EasyCellularConnection(CellularDevice *device) : _is_ini
|
|||
|
||||
EasyCellularConnection::~EasyCellularConnection()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
nsapi_error_t EasyCellularConnection::init()
|
||||
{
|
||||
nsapi_error_t err = NSAPI_ERROR_OK;
|
||||
_stm_error = false;
|
||||
if (!_is_initialized) {
|
||||
#if defined (MDMRTS) && defined (MDMCTS)
|
||||
_serial.set_flow_control(SerialBase::RTSCTS, MDMRTS, MDMCTS);
|
||||
#endif
|
||||
err = _device->init_stm(&_serial);
|
||||
if (err != NSAPI_ERROR_OK) {
|
||||
return NSAPI_ERROR_NO_MEMORY;
|
||||
}
|
||||
|
||||
_context->attach(callback(this, &EasyCellularConnection::network_callback));
|
||||
err = _device->start_dispatch();
|
||||
if (err != NSAPI_ERROR_OK) {
|
||||
return NSAPI_ERROR_NO_MEMORY;
|
||||
}
|
||||
|
||||
_network = _device->open_network(&_serial);
|
||||
_device->attach(callback(this, &EasyCellularConnection::network_callback));
|
||||
_is_initialized = true;
|
||||
}
|
||||
|
||||
|
@ -85,15 +74,13 @@ void EasyCellularConnection::set_credentials(const char *apn, const char *uname,
|
|||
{
|
||||
if (apn && strlen(apn) > 0) {
|
||||
_credentials_err = init();
|
||||
|
||||
if (_credentials_err) {
|
||||
return;
|
||||
}
|
||||
_credentials_err = _device->set_credentials(apn, uname, pwd);
|
||||
|
||||
_context->set_apn_credentials(apn, uname, pwd);
|
||||
#if USE_APN_LOOKUP
|
||||
if (_credentials_err == NSAPI_ERROR_OK) {
|
||||
_credentials_set = true;
|
||||
}
|
||||
_credentials_set = true;
|
||||
#endif // #if USE_APN_LOOKUP
|
||||
}
|
||||
}
|
||||
|
@ -101,17 +88,13 @@ void EasyCellularConnection::set_credentials(const char *apn, const char *uname,
|
|||
void EasyCellularConnection::set_sim_pin(const char *sim_pin)
|
||||
{
|
||||
if (sim_pin && strlen(sim_pin) > 0) {
|
||||
_credentials_err = init();
|
||||
if (_credentials_err) {
|
||||
return;
|
||||
}
|
||||
_device->set_sim_pin(sim_pin);
|
||||
}
|
||||
}
|
||||
|
||||
nsapi_error_t EasyCellularConnection::connect(const char *sim_pin, const char *apn, const char *uname, const char *pwd)
|
||||
{
|
||||
if (_device->is_connected()) {
|
||||
if (_context->is_connected()) {
|
||||
return NSAPI_ERROR_IS_CONNECTED;
|
||||
}
|
||||
|
||||
|
@ -129,7 +112,7 @@ nsapi_error_t EasyCellularConnection::connect(const char *sim_pin, const char *a
|
|||
|
||||
nsapi_error_t EasyCellularConnection::check_connect()
|
||||
{
|
||||
if (_device->is_connected()) {
|
||||
if (_context->is_connected()) {
|
||||
return NSAPI_ERROR_IS_CONNECTED;
|
||||
}
|
||||
|
||||
|
@ -155,11 +138,11 @@ nsapi_error_t EasyCellularConnection::connect()
|
|||
|
||||
#if USE_APN_LOOKUP
|
||||
if (!_credentials_set) {
|
||||
err = _device->set_sim_ready();
|
||||
err = _context->set_sim_ready();
|
||||
if (err == NSAPI_ERROR_OK) {
|
||||
char imsi[MAX_IMSI_LENGTH + 1];
|
||||
wait(1); // need to wait to access SIM in some modems
|
||||
CellularSIM* sim = _device->open_sim(&_serial);
|
||||
CellularSIM* sim = _device->open_sim(&_device->get_filehandle());
|
||||
err = sim->get_imsi(imsi);
|
||||
if (err == NSAPI_ERROR_OK) {
|
||||
const char *apn_config = apnconfig(imsi);
|
||||
|
@ -168,19 +151,19 @@ nsapi_error_t EasyCellularConnection::connect()
|
|||
const char *uname = _APN_GET(apn_config);
|
||||
const char *pwd = _APN_GET(apn_config);
|
||||
tr_info("Looked up APN %s", apn);
|
||||
err = _device->set_credentials(apn, uname, pwd);
|
||||
_context->set_apn_credentials(apn, uname, pwd);
|
||||
}
|
||||
}
|
||||
_device->close_sim();
|
||||
}
|
||||
if (err) {
|
||||
} else {
|
||||
tr_error("APN lookup failed");
|
||||
return err;
|
||||
}
|
||||
}
|
||||
#endif // USE_APN_LOOKUP
|
||||
|
||||
err = _device->connect();
|
||||
|
||||
err = _context->connect();
|
||||
if (err != NSAPI_ERROR_OK) {
|
||||
tr_info("No cellular connection");
|
||||
err = NSAPI_ERROR_NO_CONNECTION;
|
||||
|
@ -192,41 +175,31 @@ nsapi_error_t EasyCellularConnection::disconnect()
|
|||
{
|
||||
_credentials_err = NSAPI_ERROR_OK;
|
||||
_is_initialized = false;
|
||||
_stm_error = false;
|
||||
#if USE_APN_LOOKUP
|
||||
_credentials_set = false;
|
||||
#endif // #if USE_APN_LOOKUP
|
||||
|
||||
return _device->disconnect();
|
||||
return _context->disconnect();
|
||||
}
|
||||
|
||||
bool EasyCellularConnection::is_connected()
|
||||
{
|
||||
return _device->is_connected();
|
||||
return _context->is_connected();
|
||||
}
|
||||
|
||||
const char *EasyCellularConnection::get_ip_address()
|
||||
{
|
||||
if (!_network) {
|
||||
return NULL;
|
||||
}
|
||||
return _network->get_ip_address();
|
||||
return _context->get_ip_address();
|
||||
}
|
||||
|
||||
const char *EasyCellularConnection::get_netmask()
|
||||
{
|
||||
if (!_network) {
|
||||
return NULL;
|
||||
}
|
||||
return _network->get_netmask();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *EasyCellularConnection::get_gateway()
|
||||
{
|
||||
if (!_network) {
|
||||
return NULL;
|
||||
}
|
||||
return _network->get_gateway();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void EasyCellularConnection::attach(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb)
|
||||
|
@ -242,19 +215,13 @@ void EasyCellularConnection::modem_debug_on(bool on)
|
|||
void EasyCellularConnection::set_plmn(const char *plmn)
|
||||
{
|
||||
if (plmn && strlen(plmn) > 0) {
|
||||
if (!_device) {
|
||||
_credentials_err = init();
|
||||
if (_credentials_err) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
_device->set_plmn(plmn);
|
||||
}
|
||||
}
|
||||
|
||||
NetworkStack *EasyCellularConnection::get_stack()
|
||||
{
|
||||
return _device->get_stack();
|
||||
return _context->get_stack();
|
||||
}
|
||||
|
||||
CellularDevice *EasyCellularConnection::get_device() const
|
||||
|
@ -264,7 +231,7 @@ CellularDevice *EasyCellularConnection::get_device() const
|
|||
|
||||
UARTSerial *EasyCellularConnection::get_serial()
|
||||
{
|
||||
return &_serial;
|
||||
return (UARTSerial*)&_device->get_filehandle();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
#if defined(CELLULAR_DEVICE) || defined(DOXYGEN_ONLY)
|
||||
|
||||
#include "CellularDevice.h"
|
||||
#include "CellularContext.h"
|
||||
#include "UARTSerial.h"
|
||||
#include "CellularBase.h"
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
|||
|
||||
namespace mbed {
|
||||
|
||||
class CellularDevice;
|
||||
/** EasyCellularConnection class
|
||||
*
|
||||
* Simplified adapter for cellular connection
|
||||
|
@ -37,7 +38,7 @@ namespace mbed {
|
|||
class EasyCellularConnection: public CellularBase {
|
||||
|
||||
public:
|
||||
EasyCellularConnection(CellularDevice *device = CellularDevice::get_default_instance());
|
||||
EasyCellularConnection(CellularContext *ctx = (CellularContext *)CellularContext::get_default_instance());
|
||||
virtual ~EasyCellularConnection();
|
||||
|
||||
public:
|
||||
|
@ -165,14 +166,12 @@ private:
|
|||
nsapi_error_t check_connect();
|
||||
|
||||
bool _is_initialized;
|
||||
bool _stm_error;
|
||||
#if USE_APN_LOOKUP
|
||||
bool _credentials_set;
|
||||
#endif // #if USE_APN_LOOKUP
|
||||
|
||||
UARTSerial _serial;
|
||||
CellularDevice *_device;
|
||||
CellularNetwork* _network;
|
||||
CellularContext* _context;
|
||||
nsapi_error_t _credentials_err;
|
||||
Callback<void(nsapi_event_t, intptr_t)> _status_cb;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,262 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef _CELLULARCONTEXT_H_
|
||||
#define _CELLULARCONTEXT_H_
|
||||
|
||||
#include "NetworkInterface.h"
|
||||
#include "CellularDevice.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
class CellularContext : public NetworkInterface {
|
||||
|
||||
public:
|
||||
// max simultaneous PDP contexts active
|
||||
static const int PDP_CONTEXT_COUNT = 4;
|
||||
|
||||
static NetworkInterface *get_default_instance();
|
||||
|
||||
/* authentication type when activating or modifying the pdp context */
|
||||
enum AuthenticationType {
|
||||
NOAUTH = 0,
|
||||
PAP,
|
||||
CHAP
|
||||
};
|
||||
|
||||
/* whether the additional exception reports are allowed to be sent when the maximum uplink rate is reached */
|
||||
enum RateControlExceptionReports {
|
||||
NotAllowedToBeSent = 0,
|
||||
AllowedToBeSent
|
||||
};
|
||||
|
||||
/* specifies the time unit to be used for the maximum uplink rate */
|
||||
enum RateControlUplinkTimeUnit {
|
||||
Unrestricted = 0,
|
||||
Minute,
|
||||
Hour,
|
||||
Day,
|
||||
Week
|
||||
};
|
||||
|
||||
/* PDP Context information */
|
||||
struct pdpcontext_params_t {
|
||||
char apn[MAX_ACCESSPOINT_NAME_LENGTH + 1];
|
||||
char local_addr[MAX_IPV6_ADDR_IN_IPV4LIKE_DOTTED_FORMAT + 1];
|
||||
char local_subnet_mask[MAX_IPV6_ADDR_IN_IPV4LIKE_DOTTED_FORMAT + 1];
|
||||
char gateway_addr[MAX_IPV6_ADDR_IN_IPV4LIKE_DOTTED_FORMAT + 1];
|
||||
char dns_primary_addr[MAX_IPV6_ADDR_IN_IPV4LIKE_DOTTED_FORMAT + 1];
|
||||
char dns_secondary_addr[MAX_IPV6_ADDR_IN_IPV4LIKE_DOTTED_FORMAT + 1];
|
||||
char p_cscf_prim_addr[MAX_IPV6_ADDR_IN_IPV4LIKE_DOTTED_FORMAT + 1];
|
||||
char p_cscf_sec_addr[MAX_IPV6_ADDR_IN_IPV4LIKE_DOTTED_FORMAT + 1];
|
||||
int cid;
|
||||
int bearer_id;
|
||||
int im_signalling_flag;
|
||||
int lipa_indication;
|
||||
int ipv4_mtu;
|
||||
int wlan_offload;
|
||||
int local_addr_ind;
|
||||
int non_ip_mtu;
|
||||
int serving_plmn_rate_control_value;
|
||||
pdpcontext_params_t *next;
|
||||
|
||||
pdpcontext_params_t()
|
||||
{
|
||||
apn[0] = '\0';
|
||||
local_addr[0] = '\0';
|
||||
local_subnet_mask[0] = '\0';
|
||||
gateway_addr[0] = '\0';
|
||||
dns_primary_addr[0] = '\0';
|
||||
dns_secondary_addr[0] = '\0';
|
||||
p_cscf_prim_addr[0] = '\0';
|
||||
p_cscf_sec_addr[0] = '\0';
|
||||
cid = -1;
|
||||
bearer_id = -1;
|
||||
im_signalling_flag = -1;
|
||||
lipa_indication = -1;
|
||||
ipv4_mtu = -1;
|
||||
wlan_offload = -1;
|
||||
local_addr_ind = -1;
|
||||
non_ip_mtu = -1;
|
||||
serving_plmn_rate_control_value = -1;
|
||||
next = NULL;
|
||||
}
|
||||
};
|
||||
typedef CellularList<pdpcontext_params_t> pdpContextList_t;
|
||||
|
||||
// pointer for next item when used as a linked list
|
||||
CellularContext* _next;
|
||||
protected:
|
||||
// friend of CellularDevice so that it's the only way to close/delete this class.
|
||||
friend class CellularDevice;
|
||||
virtual ~CellularContext() {}
|
||||
|
||||
public: // from NetworkInterface
|
||||
virtual nsapi_error_t set_blocking(bool blocking) = 0;
|
||||
virtual NetworkStack *get_stack() = 0;
|
||||
virtual const char *get_ip_address() = 0;
|
||||
virtual void attach(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb) = 0;
|
||||
virtual nsapi_error_t connect() = 0;
|
||||
virtual nsapi_error_t disconnect() = 0;
|
||||
virtual bool is_connected() = 0;
|
||||
|
||||
public:
|
||||
|
||||
/** Start the interface
|
||||
*
|
||||
* Power on the device and does the initializations for communication with the modem..
|
||||
* By default this API is synchronous. API can be set to asynchronous with method set_blocking(...).
|
||||
* In synchronous and asynchronous mode application can get result in from callback which is set with
|
||||
* attach(...)
|
||||
*
|
||||
* @return NSAPI_ERROR_OK on success
|
||||
* NSAPI_ERROR_NO_MEMORY on case of memory failure
|
||||
*/
|
||||
virtual nsapi_error_t set_device_ready() = 0;
|
||||
|
||||
/** Start the interface
|
||||
*
|
||||
* Attempts to open the sim.
|
||||
* By default this API is synchronous. API can be set to asynchronous with method set_blocking(...).
|
||||
* In synchronous and asynchronous mode application can get result in from callback which is set with
|
||||
* attach(...)
|
||||
*
|
||||
* @return NSAPI_ERROR_OK on success
|
||||
* NSAPI_ERROR_NO_MEMORY on case of memory failure
|
||||
*/
|
||||
virtual nsapi_error_t set_sim_ready() = 0;
|
||||
|
||||
/** Start the interface
|
||||
*
|
||||
* Attempts to register the device to cellular network.
|
||||
* By default this API is synchronous. API can be set to asynchronous with method set_blocking(...).
|
||||
* In synchronous and asynchronous mode application can get result in from callback which is set with
|
||||
* attach(...)
|
||||
*
|
||||
* @return NSAPI_ERROR_OK on success
|
||||
* NSAPI_ERROR_NO_MEMORY on case of memory failure
|
||||
*/
|
||||
virtual nsapi_error_t register_to_network() = 0;
|
||||
|
||||
/** Start the interface
|
||||
*
|
||||
* Attempts to attach the device to cellular network.
|
||||
* By default this API is synchronous. API can be set to asynchronous with method set_blocking(...).
|
||||
* In synchronous and asynchronous mode application can get result in from callback which is set with
|
||||
* attach(...)
|
||||
*
|
||||
* @return NSAPI_ERROR_OK on success
|
||||
* NSAPI_ERROR_NO_MEMORY on case of memory failure
|
||||
*/
|
||||
virtual nsapi_error_t attach_to_network() = 0;
|
||||
|
||||
public:
|
||||
|
||||
/** Get APN rate control.
|
||||
*
|
||||
* @remark optional params are not updated if not received from network, so use good defaults
|
||||
* @param reports Additional exception reports at maximum rate reached are allowed to be sent [optional]
|
||||
* @param time_unit Uplink time unit with values 0=unrestricted, 1=minute, 2=hour, 3=day, 4=week [optional]
|
||||
* @param uplink_rate Maximum number of messages per timeUnit [optional]
|
||||
* @return NSAPI_ERROR_OK on success
|
||||
* NSAPI_ERROR_DEVICE_ERROR on case of failure
|
||||
*/
|
||||
virtual nsapi_error_t get_rate_control(CellularContext::RateControlExceptionReports &reports,
|
||||
CellularContext::RateControlUplinkTimeUnit &time_unit, int &uplink_rate) = 0;
|
||||
|
||||
/** Get the relevant information for an active non secondary PDP context.
|
||||
*
|
||||
* @remark optional params are not updated if not received from network.
|
||||
* @param params_list reference to linked list, which is filled on successful call
|
||||
* @return NSAPI_ERROR_OK on success
|
||||
* NSAPI_ERROR_NO_MEMORY on memory failure
|
||||
* NSAPI_ERROR_DEVICE_ERROR on other failures
|
||||
*/
|
||||
virtual nsapi_error_t get_pdpcontext_params(pdpContextList_t ¶ms_list) = 0;
|
||||
|
||||
/** Get backoff timer value
|
||||
*
|
||||
* @param backoff_timer Backoff timer value associated with PDP APN in seconds
|
||||
* @return NSAPI_ERROR_OK on success
|
||||
* NSAPI_ERROR_PARAMETER if no access point is set or found when activating context
|
||||
* NSAPI_ERROR_DEVICE_ERROR on failure
|
||||
*/
|
||||
virtual nsapi_error_t get_apn_backoff_timer(int &backoff_timer) = 0;
|
||||
|
||||
/** Set the cellular network APN and credentials
|
||||
*
|
||||
* @param apn Optional name of the network to connect to
|
||||
* @param uname Optional username for the APN
|
||||
* @param pwd Optional password for the APN
|
||||
*/
|
||||
virtual void set_apn_credentials(const char *uname = 0, const char *pwd = 0,
|
||||
CellularContext::AuthenticationType type = CellularContext::CHAP) = 0;
|
||||
|
||||
/** Set the cellular network APN and credentials
|
||||
*
|
||||
* @param apn Name of the network to connect to
|
||||
* @param uname Optional username for the APN
|
||||
* @param pwd Optional password for the APN
|
||||
* @param type Optional authentication type to use
|
||||
*/
|
||||
virtual void set_apn_credentials(const char* apn, const char *uname = 0, const char *pwd = 0,
|
||||
CellularContext::AuthenticationType type = CellularContext::CHAP) = 0;
|
||||
|
||||
/** Set the file handle used to communicate with the modem. Can be used to change default file handle.
|
||||
*
|
||||
* @param fh file handle for communicating with the modem
|
||||
*/
|
||||
virtual void set_file_handle(FileHandle *fh) = 0;
|
||||
|
||||
protected:
|
||||
enum ContextOperation {
|
||||
OP_INVALID = -1,
|
||||
OP_DEVICE_READY = 0,
|
||||
OP_SIM_READY = 1,
|
||||
OP_REGISTER = 2,
|
||||
OP_ATTACH = 3 ,
|
||||
OP_CONNECT = 4,
|
||||
OP_MAX = 5
|
||||
};
|
||||
|
||||
/** Status callback function will be called on status changes on the network or CellularDevice
|
||||
* by the CellularDevice.
|
||||
*
|
||||
* @param ev event type
|
||||
* @param ptr event-type dependent reason parameter
|
||||
*/
|
||||
virtual void cellular_callback(nsapi_event_t ev, intptr_t ptr) = 0;
|
||||
|
||||
// member variables needed in target override methods
|
||||
NetworkStack *_stack; // must be pointer because of PPP
|
||||
nsapi_ip_stack_t _ip_stack_type;
|
||||
CellularContext::AuthenticationType _authentication_type;
|
||||
nsapi_connection_status_t _connect_status;
|
||||
cell_callback_data_t _cb_data;
|
||||
Callback<void(nsapi_event_t, intptr_t)> _status_cb;
|
||||
int _cid;
|
||||
bool _new_context_set;
|
||||
bool _is_context_active;
|
||||
bool _is_context_activated; // did we activate the context
|
||||
const char *_apn;
|
||||
const char *_uname;
|
||||
const char *_pwd;
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
||||
|
||||
#endif /* _CELLULARCONTEXT_H_ */
|
|
@ -20,8 +20,6 @@
|
|||
|
||||
#include "CellularStateMachine.h"
|
||||
|
||||
class NetworkStack;
|
||||
|
||||
namespace mbed {
|
||||
|
||||
class CellularPower;
|
||||
|
@ -29,8 +27,12 @@ class CellularSMS;
|
|||
class CellularSIM;
|
||||
class CellularInformation;
|
||||
class CellularNetwork;
|
||||
class CellularContext;
|
||||
class FileHandle;
|
||||
|
||||
const int MAX_PIN_SIZE = 8;
|
||||
const int MAX_PLMN_SIZE = 16;
|
||||
|
||||
/**
|
||||
* Class CellularDevice
|
||||
*
|
||||
|
@ -53,6 +55,12 @@ public:
|
|||
*/
|
||||
virtual events::EventQueue *get_queue() const;
|
||||
|
||||
/** Get filehandle
|
||||
*
|
||||
* @return Filehandle used in CellularDevice. With AT it's UARTSerial.
|
||||
*/
|
||||
FileHandle &get_filehandle() const;
|
||||
|
||||
/** Default constructor
|
||||
*/
|
||||
CellularDevice();
|
||||
|
@ -62,40 +70,65 @@ public:
|
|||
virtual ~CellularDevice();
|
||||
|
||||
public:
|
||||
|
||||
/** Creates a new CellularContext interface. There can be multiple CellularContext interfaces unlike
|
||||
* open_xxx(...) methods.
|
||||
*
|
||||
* @param fh file handle used in communication to modem. Can be for example UART handle. If null then the default
|
||||
* file handle is used.
|
||||
* @param apn access point to use with context, can be null.
|
||||
* @param stack stack to be used when finding suitable PDP context
|
||||
*
|
||||
* @return new instance of class CellularContext or NULL in case of failure
|
||||
*
|
||||
*/
|
||||
virtual CellularContext *create_context(FileHandle *fh = NULL, const char *apn = MBED_CONF_NSAPI_DEFAULT_CELLULAR_APN, nsapi_ip_stack_t stack = DEFAULT_STACK) = 0;
|
||||
|
||||
/** Deletes the given CellularContext instance
|
||||
*
|
||||
* @param context to delete
|
||||
*/
|
||||
virtual void delete_context(CellularContext *context) = 0;
|
||||
|
||||
/** Create new CellularNetwork interface.
|
||||
*
|
||||
* @param fh file handle used in communication to modem. Can be for example UART handle.
|
||||
* @param fh file handle used in communication to modem. Can be for example UART handle. If null then the default
|
||||
* file handle is used.
|
||||
* @return New instance of interface CellularNetwork.
|
||||
*/
|
||||
virtual CellularNetwork *open_network(FileHandle *fh) = 0;
|
||||
virtual CellularNetwork *open_network(FileHandle *fh = NULL) = 0;
|
||||
|
||||
/** Create new CellularSMS interface.
|
||||
*
|
||||
* @param fh file handle used in communication to modem. Can be for example UART handle.
|
||||
* @param fh file handle used in communication to modem. Can be for example UART handle. If null then the default
|
||||
* file handle is used.
|
||||
* @return New instance of interface CellularSMS.
|
||||
*/
|
||||
virtual CellularSMS *open_sms(FileHandle *fh) = 0;
|
||||
virtual CellularSMS *open_sms(FileHandle *fh = NULL) = 0;
|
||||
|
||||
/** Create new CellularPower interface.
|
||||
*
|
||||
* @param fh file handle used in communication to modem. Can be for example UART handle.
|
||||
* @param fh file handle used in communication to modem. Can be for example UART handle. If null then the default
|
||||
* file handle is used.
|
||||
* @return New instance of interface CellularPower.
|
||||
*/
|
||||
virtual CellularPower *open_power(FileHandle *fh) = 0;
|
||||
virtual CellularPower *open_power(FileHandle *fh = NULL) = 0;
|
||||
|
||||
/** Create new CellularSIM interface.
|
||||
*
|
||||
* @param fh file handle used in communication to modem. Can be for example UART handle.
|
||||
* @param fh file handle used in communication to modem. Can be for example UART handle. If null then the default
|
||||
* file handle is used.
|
||||
* @return New instance of interface CellularSIM.
|
||||
*/
|
||||
virtual CellularSIM *open_sim(FileHandle *fh) = 0;
|
||||
virtual CellularSIM *open_sim(FileHandle *fh = NULL) = 0;
|
||||
|
||||
/** Create new CellularInformation interface.
|
||||
*
|
||||
* @param fh file handle used in communication to modem. Can be for example UART handle.
|
||||
* @param fh file handle used in communication to modem. Can be for example UART handle. If null then the default
|
||||
* file handle is used.
|
||||
* @return New instance of interface CellularInformation.
|
||||
*/
|
||||
virtual CellularInformation *open_information(FileHandle *fh) = 0;
|
||||
virtual CellularInformation *open_information(FileHandle *fh = NULL) = 0;
|
||||
|
||||
/** Closes the opened CellularNetwork by deleting the CellularNetwork instance.
|
||||
*/
|
||||
|
@ -129,12 +162,6 @@ public:
|
|||
*/
|
||||
virtual void modem_debug_on(bool on) = 0;
|
||||
|
||||
/** Get network stack.
|
||||
*
|
||||
* @return network stack
|
||||
*/
|
||||
virtual NetworkStack *get_stack() = 0;
|
||||
|
||||
/** Initialize cellular module must be called right after module is ready.
|
||||
* For example, when multiple modules are supported in a single AT driver this function detects
|
||||
* and adapts to an actual module at runtime.
|
||||
|
@ -147,33 +174,6 @@ public:
|
|||
|
||||
public:
|
||||
|
||||
/** Inits the internal state machine.
|
||||
*
|
||||
* @remark MUST be called if internal state machine is to be used. All the following public methods place in to this
|
||||
* category.
|
||||
*
|
||||
* @param fh file handle to be used as serial. Can be for example UARTSerial
|
||||
*/
|
||||
nsapi_error_t init_stm(FileHandle *fh);
|
||||
|
||||
/** Check if the connection is currently established or not
|
||||
*
|
||||
* @return true/false If the cellular module have successfully acquired a carrier and is
|
||||
* connected to an external packet data network using PPP, isConnected()
|
||||
* API returns true and false otherwise.
|
||||
*/
|
||||
bool is_connected() const;
|
||||
|
||||
/** Register callback for status reporting
|
||||
*
|
||||
* The specified status callback function will be called on status changes
|
||||
* on the network and modem. The parameters on the callback are the event type and struct cell_callback_data_t
|
||||
* giving more information about the event.
|
||||
*
|
||||
* @param status_cb The callback for status changes
|
||||
*/
|
||||
void attach(Callback<void(nsapi_event_t, intptr_t)> status_cb);
|
||||
|
||||
/** Start event queue dispatching in internal state machine by creating a new thread.
|
||||
*
|
||||
* @return NSAPI_ERROR_OK on success
|
||||
|
@ -186,21 +186,6 @@ public:
|
|||
*/
|
||||
void stop();
|
||||
|
||||
/** By default operations are synchronous. This method can toggle between sync/async.
|
||||
*
|
||||
*/
|
||||
void set_blocking(bool blocking);
|
||||
|
||||
/** Set the Cellular network credentials
|
||||
*
|
||||
* Please check documentation of connect() for default behaviour of APN settings.
|
||||
*
|
||||
* @param apn Access point name
|
||||
* @param uname optionally, Username
|
||||
* @param pwd optionally, password
|
||||
*/
|
||||
nsapi_error_t set_credentials(const char *apn, const char *uname = 0, const char *pwd = 0);
|
||||
|
||||
/** Set the pin code for SIM card
|
||||
*
|
||||
* @param sim_pin PIN for the SIM card
|
||||
|
@ -215,7 +200,8 @@ public:
|
|||
*/
|
||||
void set_plmn(const char* plmn);
|
||||
|
||||
public: // Operations that can be sync/async
|
||||
public: // Operations that can be sync/async, CellularContext will use these
|
||||
friend class CellularContext;
|
||||
|
||||
/** Start the interface
|
||||
*
|
||||
|
@ -265,65 +251,35 @@ public: // Operations that can be sync/async
|
|||
*/
|
||||
nsapi_error_t attach_to_network();
|
||||
|
||||
/** Start the interface
|
||||
/** Cellular callback which is called by Network class after this class attaches to it, CellularStateMachine
|
||||
* and CellularContext when in PPP mode. This method will broadcast to every interested classes:
|
||||
* CellularContext (might be many) and CellularStateMachine if available.
|
||||
*
|
||||
* Attempts to activate PDP context.
|
||||
* By default this API is synchronous. API can be set to asynchronous with method set_blocking(...).
|
||||
* In synchronous and asynchronous mode application can get result in from callback which is set with
|
||||
* attach(...)
|
||||
*
|
||||
* @return NSAPI_ERROR_OK on success
|
||||
* NSAPI_ERROR_NO_MEMORY on case of memory failure
|
||||
*/
|
||||
nsapi_error_t activate_context();
|
||||
void cellular_callback(nsapi_event_t ev, intptr_t ptr);
|
||||
|
||||
/** Start the interface
|
||||
/** Get the linked list of CellularContext instances
|
||||
*
|
||||
* Attempts to connect to a Cellular network.
|
||||
* By default this API is synchronous. API can be set to asynchronous with method set_blocking(...).
|
||||
* In synchronous and asynchronous mode application can get result in from callback which is set with
|
||||
* attach(...)
|
||||
*
|
||||
* @param sim_pin PIN for the SIM card
|
||||
* @param apn optionally, access point name
|
||||
* @param uname optionally, Username
|
||||
* @param pwd optionally, password
|
||||
* @return NSAPI_ERROR_OK on success, or negative error code on failure
|
||||
* @return Pointer to first item in linked list
|
||||
*/
|
||||
nsapi_error_t connect(const char *sim_pin, const char *apn = 0, const char *uname = 0, const char *pwd = 0);
|
||||
virtual CellularContext *get_context_list() const;
|
||||
|
||||
/** Start the interface
|
||||
*
|
||||
* Attempts to connect to a Cellular network.
|
||||
* By default this API is synchronous. API can be set to asynchronous with method set_blocking(...).
|
||||
* In synchronous and asynchronous mode application can get result in from callback which is set with
|
||||
* attach(...)
|
||||
* If the SIM requires a PIN, and it is not set/invalid, NSAPI_ERROR_AUTH_ERROR is returned.
|
||||
*
|
||||
* @return NSAPI_ERROR_OK on success, or negative error code on failure
|
||||
*/
|
||||
nsapi_error_t connect();
|
||||
|
||||
/** Stop the interface
|
||||
*
|
||||
* @return 0 on success, or error code on failure
|
||||
*/
|
||||
nsapi_error_t disconnect();
|
||||
|
||||
private:
|
||||
void network_callback(nsapi_event_t ev, intptr_t ptr);
|
||||
Callback<void(nsapi_event_t, intptr_t)> _nw_status_cb;
|
||||
|
||||
protected:
|
||||
nsapi_error_t _error;
|
||||
int _network_ref_count;
|
||||
int _sms_ref_count;
|
||||
int _power_ref_count;
|
||||
int _sim_ref_count;
|
||||
int _info_ref_count;
|
||||
bool _is_connected;
|
||||
CellularStateMachine *_state_machine;
|
||||
FileHandle *_fh;
|
||||
private:
|
||||
nsapi_error_t start_state_machine(CellularStateMachine::CellularState target_state);
|
||||
void create_state_machine();
|
||||
|
||||
nsapi_error_t _error;
|
||||
CellularStateMachine *_state_machine;
|
||||
CellularNetwork *_nw;
|
||||
char _sim_pin[MAX_PIN_SIZE + 1];
|
||||
char _plmn[MAX_PLMN_SIZE +1];
|
||||
PlatformMutex _mutex;
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
|
|
@ -18,8 +18,9 @@
|
|||
#ifndef CELLULAR_NETWORK_H_
|
||||
#define CELLULAR_NETWORK_H_
|
||||
|
||||
#include "NetworkInterface.h"
|
||||
#include "CellularList.h"
|
||||
#include "Callback.h"
|
||||
#include "nsapi_types.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
|
@ -35,7 +36,7 @@ const int MAX_OPERATOR_NAME_SHORT = 8;
|
|||
*
|
||||
* An abstract interface for connecting to a network and getting information from it.
|
||||
*/
|
||||
class CellularNetwork : public NetworkInterface {
|
||||
class CellularNetwork {
|
||||
protected:
|
||||
// friend of CellularDevice so that it's the only way to close/delete this class.
|
||||
friend class CellularDevice;
|
||||
|
@ -94,28 +95,6 @@ public:
|
|||
Attached,
|
||||
};
|
||||
|
||||
/* whether the additional exception reports are allowed to be sent when the maximum uplink rate is reached */
|
||||
enum RateControlExceptionReports {
|
||||
NotAllowedToBeSent = 0,
|
||||
AllowedToBeSent
|
||||
};
|
||||
|
||||
/* specifies the time unit to be used for the maximum uplink rate */
|
||||
enum RateControlUplinkTimeUnit {
|
||||
Unrestricted = 0,
|
||||
Minute,
|
||||
Hour,
|
||||
Day,
|
||||
Week
|
||||
};
|
||||
|
||||
/* authentication type when activating or modifying the pdp context */
|
||||
enum AuthenticationType {
|
||||
NOAUTH = 0,
|
||||
PAP,
|
||||
CHAP
|
||||
};
|
||||
|
||||
enum RadioAccessTechnology {
|
||||
RAT_GSM,
|
||||
RAT_GSM_COMPACT,
|
||||
|
@ -159,51 +138,6 @@ public:
|
|||
|
||||
typedef CellularList<operator_t> operList_t;
|
||||
|
||||
/* PDP Context information */
|
||||
struct pdpcontext_params_t {
|
||||
char apn[MAX_ACCESSPOINT_NAME_LENGTH + 1];
|
||||
char local_addr[MAX_IPV6_ADDR_IN_IPV4LIKE_DOTTED_FORMAT + 1];
|
||||
char local_subnet_mask[MAX_IPV6_ADDR_IN_IPV4LIKE_DOTTED_FORMAT + 1];
|
||||
char gateway_addr[MAX_IPV6_ADDR_IN_IPV4LIKE_DOTTED_FORMAT + 1];
|
||||
char dns_primary_addr[MAX_IPV6_ADDR_IN_IPV4LIKE_DOTTED_FORMAT + 1];
|
||||
char dns_secondary_addr[MAX_IPV6_ADDR_IN_IPV4LIKE_DOTTED_FORMAT + 1];
|
||||
char p_cscf_prim_addr[MAX_IPV6_ADDR_IN_IPV4LIKE_DOTTED_FORMAT + 1];
|
||||
char p_cscf_sec_addr[MAX_IPV6_ADDR_IN_IPV4LIKE_DOTTED_FORMAT + 1];
|
||||
int cid;
|
||||
int bearer_id;
|
||||
int im_signalling_flag;
|
||||
int lipa_indication;
|
||||
int ipv4_mtu;
|
||||
int wlan_offload;
|
||||
int local_addr_ind;
|
||||
int non_ip_mtu;
|
||||
int serving_plmn_rate_control_value;
|
||||
pdpcontext_params_t *next;
|
||||
|
||||
pdpcontext_params_t()
|
||||
{
|
||||
apn[0] = '\0';
|
||||
local_addr[0] = '\0';
|
||||
local_subnet_mask[0] = '\0';
|
||||
gateway_addr[0] = '\0';
|
||||
dns_primary_addr[0] = '\0';
|
||||
dns_secondary_addr[0] = '\0';
|
||||
p_cscf_prim_addr[0] = '\0';
|
||||
p_cscf_sec_addr[0] = '\0';
|
||||
cid = -1;
|
||||
bearer_id = -1;
|
||||
im_signalling_flag = -1;
|
||||
lipa_indication = -1;
|
||||
ipv4_mtu = -1;
|
||||
wlan_offload = -1;
|
||||
local_addr_ind = -1;
|
||||
non_ip_mtu = -1;
|
||||
serving_plmn_rate_control_value = -1;
|
||||
next = NULL;
|
||||
}
|
||||
};
|
||||
typedef CellularList<pdpcontext_params_t> pdpContextList_t;
|
||||
|
||||
struct operator_names_t {
|
||||
char numeric[MAX_OPERATOR_NAME_SHORT + 1];
|
||||
char alpha[MAX_OPERATOR_NAME_LONG + 1];
|
||||
|
@ -248,14 +182,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/** Does all the needed initializations that can fail
|
||||
*
|
||||
* @remark must be called immediately after constructor.
|
||||
* @return NSAPI_ERROR_OK on success
|
||||
* NSAPI_ERROR_NO_MEMORY on memory failure
|
||||
*/
|
||||
virtual nsapi_error_t init() = 0;
|
||||
|
||||
/** Request registering to network.
|
||||
*
|
||||
* @param plmn format is in numeric format or 0 for automatic network registration
|
||||
|
@ -286,38 +212,12 @@ public:
|
|||
virtual nsapi_error_t set_registration_urc(RegistrationType type, bool on) = 0;
|
||||
|
||||
|
||||
/** Set the cellular network APN and credentials
|
||||
*
|
||||
* @param apn Optional name of the network to connect to
|
||||
* @param username Optional username for the APN
|
||||
* @param password Optional password fot the APN
|
||||
* @return NSAPI_ERROR_OK on success
|
||||
* NSAPI_ERROR_NO_MEMORY on memory failure
|
||||
*/
|
||||
virtual nsapi_error_t set_credentials(const char *apn,
|
||||
const char *username = 0, const char *password = 0) = 0;
|
||||
|
||||
/** Set the cellular network APN and credentials
|
||||
*
|
||||
* @param apn Name of the network to connect to
|
||||
* @param type Authentication type to use
|
||||
* @param username Optional username for the APN
|
||||
* @param password Optional password fot the APN
|
||||
* @return NSAPI_ERROR_OK on success
|
||||
* NSAPI_ERROR_NO_MEMORY on memory failure
|
||||
*/
|
||||
virtual nsapi_error_t set_credentials(const char *apn, AuthenticationType type,
|
||||
const char *username = 0, const char *password = 0) = 0;
|
||||
|
||||
/** Request attach to network.
|
||||
*
|
||||
* @deprecated Parameter timeout will be deprecated. Use mbed-os/features/cellular/framework/API/CellularDevice.h set_timeout instead.
|
||||
* @param timeout milliseconds to wait for attach response
|
||||
* @return NSAPI_ERROR_OK on success
|
||||
* NSAPI_ERROR_DEVICE_ERROR on failure
|
||||
*/
|
||||
MBED_DEPRECATED_SINCE("mbed-os-5.9", "Parameter timeout will be deprecated. Use mbed-os/features/cellular/framework/API/CellularDevice.h set_timeout instead.")
|
||||
virtual nsapi_error_t set_attach(int timeout = 10 * 1000) = 0;
|
||||
virtual nsapi_error_t set_attach() = 0;
|
||||
|
||||
/** Request attach status from network.
|
||||
*
|
||||
|
@ -334,27 +234,6 @@ public:
|
|||
*/
|
||||
virtual nsapi_error_t detach() = 0;
|
||||
|
||||
/** Get APN rate control.
|
||||
*
|
||||
* @remark optional params are not updated if not received from network, so use good defaults
|
||||
* @param reports Additional exception reports at maximum rate reached are allowed to be sent [optional]
|
||||
* @param time_unit Uplink time unit with values 0=unrestricted, 1=minute, 2=hour, 3=day, 4=week [optional]
|
||||
* @param uplink_rate Maximum number of messages per timeUnit [optional]
|
||||
* @return NSAPI_ERROR_OK on success
|
||||
* NSAPI_ERROR_DEVICE_ERROR on case of failure
|
||||
*/
|
||||
virtual nsapi_error_t get_rate_control(CellularNetwork::RateControlExceptionReports &reports,
|
||||
CellularNetwork::RateControlUplinkTimeUnit &time_unit, int &uplink_rate) = 0;
|
||||
|
||||
/** Get backoff timer value
|
||||
*
|
||||
* @param backoff_timer Backoff timer value associated with PDP APN in seconds
|
||||
* @return NSAPI_ERROR_OK on success
|
||||
* NSAPI_ERROR_PARAMETER if no access point is set or found when activating context
|
||||
* NSAPI_ERROR_DEVICE_ERROR on failure
|
||||
*/
|
||||
virtual nsapi_error_t get_apn_backoff_timer(int &backoff_timer) = 0;
|
||||
|
||||
/** Sets radio access technology.
|
||||
*
|
||||
* @param rat Radio access technology
|
||||
|
@ -395,70 +274,6 @@ public:
|
|||
virtual nsapi_error_t get_ciot_optimization_config(Supported_UE_Opt &supported_opt,
|
||||
Preferred_UE_Opt &preferred_opt) = 0;
|
||||
|
||||
/** Start the interface. Attempts to connect to a cellular network.
|
||||
*
|
||||
* @return NSAPI_ERROR_OK on success
|
||||
* NSAPI_ERROR_NO_CONNECTION if fails to find suitable context to activate or activation failed (if not already activated)
|
||||
* NSAPI_ERROR_UNSUPPORTED if NetworkStack was not found or cellular device does not support authentication
|
||||
* NSAPI_ERROR_AUTH_FAILURE if password and username were provided and authentication to network failed
|
||||
* Also if PPP mode
|
||||
* NSAPI_ERROR_DEVICE_ERROR on failure and check more error from nsapi_ppp_connect(...)
|
||||
*/
|
||||
virtual nsapi_error_t connect() = 0;
|
||||
|
||||
/** Start the interface. Attempts to connect to a cellular network.
|
||||
*
|
||||
* @param apn Optional name of the network to connect to
|
||||
* @param username Optional username for your APN
|
||||
* @param password Optional password for your APN
|
||||
* @return NSAPI_ERROR_OK on success
|
||||
* NSAPI_ERROR_NO_CONNECTION if fails to find suitable context to activate or activation failed (if not already activated)
|
||||
* NSAPI_ERROR_UNSUPPORTED if NetworkStack was not found
|
||||
* NSAPI_ERROR_AUTH_FAILURE if password and username were provided and authentication to network failed
|
||||
* NSAPI_ERROR_NO_MEMORY on memory failure
|
||||
* Also if PPP mode
|
||||
* NSAPI_ERROR_DEVICE_ERROR on failure and check more error from nsapi_ppp_connect(...)
|
||||
*/
|
||||
virtual nsapi_error_t connect(const char *apn,
|
||||
const char *username = 0, const char *password = 0) = 0;
|
||||
|
||||
/** Finds the correct PDP context and activates it. If correct PDP context is not found, one is created.
|
||||
* Given APN (or not given) and stack type (IPv4/IPv6/dual) are influencing when finding the PDP context.
|
||||
*
|
||||
* @return NSAPI_ERROR_OK on success
|
||||
* NSAPI_ERROR_NO_CONNECTION if fails to find suitable context to activate or activation failed (if not already activated)
|
||||
* NSAPI_ERROR_UNSUPPORTED if NetworkStack was not found
|
||||
* NSAPI_ERROR_AUTH_FAILURE if password and username were provided and authentication to network failed
|
||||
*/
|
||||
virtual nsapi_error_t activate_context() = 0;
|
||||
|
||||
/**
|
||||
* Set the pdn type to be used
|
||||
*
|
||||
* @param stack_type the stack type to be used.
|
||||
*
|
||||
* @return NSAPI_ERROR_OK on success
|
||||
* NSAPI_ERROR_PARAMETER if modem does not support the given stack_type
|
||||
*/
|
||||
virtual nsapi_error_t set_stack_type(nsapi_ip_stack_t stack_type) = 0;
|
||||
|
||||
/**
|
||||
* Get the pdn type in use
|
||||
*
|
||||
* @return stack type
|
||||
*/
|
||||
virtual nsapi_ip_stack_t get_stack_type() = 0;
|
||||
|
||||
/** Get the relevant information for an active non secondary PDP context.
|
||||
*
|
||||
* @remark optional params are not updated if not received from network.
|
||||
* @param params_list reference to linked list, which is filled on successful call
|
||||
* @return NSAPI_ERROR_OK on success
|
||||
* NSAPI_ERROR_NO_MEMORY on memory failure
|
||||
* NSAPI_ERROR_DEVICE_ERROR on other failures
|
||||
*/
|
||||
virtual nsapi_error_t get_pdpcontext_params(pdpContextList_t ¶ms_list) = 0;
|
||||
|
||||
/** Get extended signal quality parameters.
|
||||
*
|
||||
* @param rxlev signal strength level
|
||||
|
@ -511,14 +326,6 @@ public:
|
|||
*/
|
||||
virtual nsapi_connection_status_t get_connection_status() const = 0;
|
||||
|
||||
/** Set blocking status of connect() which by default should be blocking
|
||||
*
|
||||
* @param blocking true if connect is blocking
|
||||
* @return NSAPI_ERROR_OK
|
||||
* if PPP mode check errors from nsapi_ppp_set_blocking(...)
|
||||
*/
|
||||
virtual nsapi_error_t set_blocking(bool blocking) = 0;
|
||||
|
||||
/** Read operator names
|
||||
*
|
||||
* @param op_names on successful return contains linked list of operator names.
|
||||
|
@ -528,6 +335,12 @@ public:
|
|||
*/
|
||||
virtual nsapi_error_t get_operator_names(operator_names_list &op_names) = 0;
|
||||
|
||||
/** Check if there is any PDP context active
|
||||
*
|
||||
* @return true is any context is active, false otherwise or in case of error
|
||||
*/
|
||||
virtual bool is_active_context() = 0;
|
||||
|
||||
/** Gets current network registration parameters:
|
||||
* type, status, access technology, cell_id, lac, active_time, periodic_tau.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,871 @@
|
|||
/*
|
||||
* 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 "AT_CellularContext.h"
|
||||
#include "AT_CellularNetwork.h"
|
||||
#include "AT_CellularStack.h"
|
||||
#include "CellularLog.h"
|
||||
#include "CellularUtil.h"
|
||||
#include "CellularSIM.h"
|
||||
#include "UARTSerial.h"
|
||||
#include "nsapi_ppp.h"
|
||||
#include "nsapi_dns.h"
|
||||
|
||||
using namespace mbed_cellular_util;
|
||||
using namespace mbed;
|
||||
|
||||
AT_CellularContext::AT_CellularContext(ATHandler &at, CellularDevice *device, const char *apn, nsapi_ip_stack_t stack) :
|
||||
AT_CellularBase(at), _ip_stack_type_requested(DEFAULT_STACK), _is_connected(false), _is_blocking(true),
|
||||
_current_op(OP_INVALID), _device(device), _nw(0), _fh(0)
|
||||
{
|
||||
tr_debug("AT_CellularContext::AT_CellularContext(): apn: %s, stack: %d", apn, stack);
|
||||
_stack = NULL;
|
||||
_ip_stack_type = DEFAULT_STACK;
|
||||
_authentication_type = CellularContext::CHAP;
|
||||
_connect_status = NSAPI_STATUS_DISCONNECTED;
|
||||
_is_context_active = false;
|
||||
_is_context_activated = false;
|
||||
_apn = apn;
|
||||
_uname = MBED_CONF_NSAPI_DEFAULT_CELLULAR_USERNAME;
|
||||
_pwd = MBED_CONF_NSAPI_DEFAULT_CELLULAR_PASSWORD;
|
||||
_status_cb = NULL;
|
||||
_cid = -1;
|
||||
_new_context_set = false;
|
||||
_next = NULL;
|
||||
}
|
||||
|
||||
AT_CellularContext::~AT_CellularContext()
|
||||
{
|
||||
(void)disconnect();
|
||||
|
||||
if (_nw) {
|
||||
_device->close_network();
|
||||
}
|
||||
}
|
||||
|
||||
void AT_CellularContext::set_file_handle(FileHandle *fh)
|
||||
{
|
||||
_fh = fh;
|
||||
_at.set_file_handle(_fh);
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularContext::connect()
|
||||
{
|
||||
if (_is_connected) {
|
||||
return NSAPI_ERROR_IS_CONNECTED;
|
||||
}
|
||||
nsapi_error_t err = _device->attach_to_network();
|
||||
_cb_data.error = check_operation(err, OP_CONNECT);
|
||||
|
||||
if (_is_blocking) {
|
||||
if (_cb_data.error == NSAPI_ERROR_OK || _cb_data.error == NSAPI_ERROR_ALREADY) {
|
||||
do_connect();
|
||||
}
|
||||
} else {
|
||||
if (_cb_data.error == NSAPI_ERROR_ALREADY) {
|
||||
// device is already attached, to be async we must use queue to connect and give proper callbacks
|
||||
int id = _device->get_queue()->call_in(0, this, &AT_CellularContext::do_connect);
|
||||
if (id == 0) {
|
||||
return NSAPI_ERROR_NO_MEMORY;
|
||||
}
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return _cb_data.error;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularContext::set_device_ready()
|
||||
{
|
||||
nsapi_error_t err = _device->set_device_ready();
|
||||
return check_operation(err, OP_DEVICE_READY);
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularContext::set_sim_ready()
|
||||
{
|
||||
nsapi_error_t err = _device->set_sim_ready();
|
||||
return check_operation(err, OP_SIM_READY);
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularContext::register_to_network()
|
||||
{
|
||||
nsapi_error_t err = _device->register_to_network();
|
||||
return check_operation(err, OP_REGISTER);
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularContext::attach_to_network()
|
||||
{
|
||||
nsapi_error_t err = _device->attach_to_network();
|
||||
return check_operation(err, OP_ATTACH);
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularContext::check_operation(nsapi_error_t err, ContextOperation op)
|
||||
{
|
||||
_current_op = op;
|
||||
if (err == NSAPI_ERROR_IN_PROGRESS || err == NSAPI_ERROR_OK) {
|
||||
if (_is_blocking) {
|
||||
int sema_err = _semaphore.wait(get_timeout_for_operation(op)); // cellular network searching may take several minutes
|
||||
if (sema_err != 1) {
|
||||
tr_warning("No cellular connection");
|
||||
return NSAPI_ERROR_TIMEOUT;
|
||||
}
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
uint32_t AT_CellularContext::get_timeout_for_operation(ContextOperation op) const
|
||||
{
|
||||
uint32_t timeout = 10 * 60 * 1000; // default timeout is 10 minutes as registration and attach may take time
|
||||
if (op == OP_SIM_READY || op == OP_DEVICE_READY) {
|
||||
timeout = 3 * 60 * 1000; // use 3 minutes for device ready and sim
|
||||
}
|
||||
return timeout;
|
||||
}
|
||||
|
||||
bool AT_CellularContext::is_connected()
|
||||
{
|
||||
return _is_connected;
|
||||
}
|
||||
|
||||
NetworkStack *AT_CellularContext::get_stack()
|
||||
{
|
||||
#if NSAPI_PPP_AVAILABLE
|
||||
// use lwIP/PPP if modem does not have IP stack
|
||||
if (!_stack) {
|
||||
_stack = nsapi_ppp_get_stack();
|
||||
}
|
||||
#endif
|
||||
return _stack;
|
||||
}
|
||||
|
||||
const char *AT_CellularContext::get_ip_address()
|
||||
{
|
||||
#if NSAPI_PPP_AVAILABLE
|
||||
return nsapi_ppp_get_ip_addr(_at.get_file_handle());
|
||||
#else
|
||||
if (!_stack) {
|
||||
_stack = get_stack();
|
||||
}
|
||||
if (_stack) {
|
||||
return _stack->get_ip_address();
|
||||
}
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
void AT_CellularContext::attach(Callback<void(nsapi_event_t, intptr_t)> status_cb)
|
||||
{
|
||||
_status_cb = status_cb;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularContext::set_blocking(bool blocking)
|
||||
{
|
||||
nsapi_error_t err = NSAPI_ERROR_OK;
|
||||
#if NSAPI_PPP_AVAILABLE
|
||||
err = nsapi_ppp_set_blocking(blocking);
|
||||
#endif
|
||||
_is_blocking = blocking;
|
||||
return err;
|
||||
}
|
||||
|
||||
void AT_CellularContext::set_apn_credentials(const char *uname, const char *pwd,
|
||||
CellularContext::AuthenticationType type) {
|
||||
|
||||
_uname = uname;
|
||||
_pwd = pwd;
|
||||
_authentication_type = type;
|
||||
}
|
||||
|
||||
void AT_CellularContext::set_apn_credentials(const char* apn, const char *uname, const char *pwd,
|
||||
CellularContext::AuthenticationType type)
|
||||
{
|
||||
_apn = apn;
|
||||
_uname = uname;
|
||||
_pwd = pwd;
|
||||
_authentication_type = type;
|
||||
}
|
||||
|
||||
bool AT_CellularContext::stack_type_supported(nsapi_ip_stack_t stack_type)
|
||||
{
|
||||
if (stack_type == _ip_stack_type) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
nsapi_ip_stack_t AT_CellularContext::get_stack_type()
|
||||
{
|
||||
return _ip_stack_type;
|
||||
}
|
||||
|
||||
nsapi_ip_stack_t AT_CellularContext::string_to_stack_type(const char *pdp_type)
|
||||
{
|
||||
nsapi_ip_stack_t stack = DEFAULT_STACK;
|
||||
int len = strlen(pdp_type);
|
||||
|
||||
if (len == 6 && memcmp(pdp_type, "IPV4V6", len) == 0) {
|
||||
stack = IPV4V6_STACK;
|
||||
} else if (len == 4 && memcmp(pdp_type, "IPV6", len) == 0) {
|
||||
stack = IPV6_STACK;
|
||||
} else if (len == 2 && memcmp(pdp_type, "IP", len) == 0) {
|
||||
stack = IPV4_STACK;
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
|
||||
// PDP Context handling
|
||||
nsapi_error_t AT_CellularContext::delete_current_context()
|
||||
{
|
||||
tr_info("Delete context %d", _cid);
|
||||
_at.clear_error();
|
||||
_at.cmd_start("AT+CGDCONT=");
|
||||
_at.write_int(_cid);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
|
||||
if (_at.get_last_error() == NSAPI_ERROR_OK) {
|
||||
_cid = -1;
|
||||
_new_context_set = false;
|
||||
}
|
||||
|
||||
return _at.get_last_error();
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularContext::do_user_authentication()
|
||||
{
|
||||
// if user has defined user name and password we need to call CGAUTH before activating or modifying context
|
||||
if (_pwd && _uname) {
|
||||
_at.cmd_start("AT+CGAUTH=");
|
||||
_at.write_int(_cid);
|
||||
_at.write_int(_authentication_type);
|
||||
_at.write_string(_uname);
|
||||
_at.write_string(_pwd);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
if (_at.get_last_error() != NSAPI_ERROR_OK) {
|
||||
return NSAPI_ERROR_AUTH_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
bool AT_CellularContext::get_context()
|
||||
{
|
||||
if (_apn) {
|
||||
tr_debug("APN in use: %s", _apn);
|
||||
} else {
|
||||
tr_debug("NO APN");
|
||||
}
|
||||
|
||||
_at.cmd_start("AT+CGDCONT?");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start("+CGDCONT:");
|
||||
_cid = -1;
|
||||
int cid_max = 0; // needed when creating new context
|
||||
char apn[MAX_ACCESSPOINT_NAME_LENGTH];
|
||||
int apn_len = 0;
|
||||
|
||||
bool modem_supports_ipv6 = stack_type_supported(IPV6_STACK);
|
||||
bool modem_supports_ipv4 = stack_type_supported(IPV4_STACK);
|
||||
|
||||
while (_at.info_resp()) {
|
||||
int cid = _at.read_int();
|
||||
if (cid > cid_max) {
|
||||
cid_max = cid;
|
||||
}
|
||||
char pdp_type_from_context[10];
|
||||
int pdp_type_len = _at.read_string(pdp_type_from_context, sizeof(pdp_type_from_context) - 1);
|
||||
if (pdp_type_len > 0) {
|
||||
apn_len = _at.read_string(apn, sizeof(apn) - 1);
|
||||
if (apn_len >= 0) {
|
||||
if (_apn && (strcmp(apn, _apn) != 0)) {
|
||||
continue;
|
||||
}
|
||||
nsapi_ip_stack_t pdp_stack = string_to_stack_type(pdp_type_from_context);
|
||||
// Accept dual PDP context for IPv4/IPv6 only modems
|
||||
if (pdp_stack != DEFAULT_STACK && (stack_type_supported(pdp_stack) || pdp_stack == IPV4V6_STACK)) {
|
||||
if (_ip_stack_type_requested == IPV4_STACK) {
|
||||
if (pdp_stack == IPV4_STACK || pdp_stack == IPV4V6_STACK) {
|
||||
_ip_stack_type = _ip_stack_type_requested;
|
||||
_cid = cid;
|
||||
break;
|
||||
}
|
||||
} else if (_ip_stack_type_requested == IPV6_STACK) {
|
||||
if (pdp_stack == IPV6_STACK || pdp_stack == IPV4V6_STACK) {
|
||||
_ip_stack_type = _ip_stack_type_requested;
|
||||
_cid = cid;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// requested dual stack or stack is not specified
|
||||
// If dual PDP need to check for IPV4 or IPV6 modem support. Prefer IPv6.
|
||||
if (pdp_stack == IPV4V6_STACK) {
|
||||
if (modem_supports_ipv6) {
|
||||
_ip_stack_type = IPV6_STACK;
|
||||
_cid = cid;
|
||||
break;
|
||||
} else if (modem_supports_ipv4) {
|
||||
_ip_stack_type = IPV4_STACK;
|
||||
_cid = cid;
|
||||
break;
|
||||
}
|
||||
// If PDP is IPV4 or IPV6 they are already checked if supported
|
||||
} else {
|
||||
_ip_stack_type = pdp_stack;
|
||||
_cid = cid;
|
||||
|
||||
if (pdp_stack == IPV6_STACK) {
|
||||
break;
|
||||
}
|
||||
if (pdp_stack == IPV4_STACK && !modem_supports_ipv6) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_at.resp_stop();
|
||||
if (_cid == -1) { // no suitable context was found so create a new one
|
||||
if (!set_new_context(cid_max + 1)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// save the apn
|
||||
if (apn_len > 0 && !_apn) {
|
||||
memcpy(_found_apn, apn, apn_len + 1);
|
||||
}
|
||||
|
||||
tr_debug("Context id %d", _cid);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AT_CellularContext::set_new_context(int cid)
|
||||
{
|
||||
nsapi_ip_stack_t tmp_stack = _ip_stack_type_requested;
|
||||
|
||||
if (tmp_stack == DEFAULT_STACK) {
|
||||
bool modem_supports_ipv6 = stack_type_supported(IPV6_STACK);
|
||||
bool modem_supports_ipv4 = stack_type_supported(IPV4_STACK);
|
||||
|
||||
if (modem_supports_ipv6 && modem_supports_ipv4) {
|
||||
tmp_stack = IPV4V6_STACK;
|
||||
} else if (modem_supports_ipv6) {
|
||||
tmp_stack = IPV6_STACK;
|
||||
} else if (modem_supports_ipv4) {
|
||||
tmp_stack = IPV4_STACK;
|
||||
}
|
||||
}
|
||||
|
||||
char pdp_type[8 + 1] = {0};
|
||||
|
||||
switch (tmp_stack) {
|
||||
case IPV4_STACK:
|
||||
strncpy(pdp_type, "IP", sizeof(pdp_type));
|
||||
break;
|
||||
case IPV6_STACK:
|
||||
strncpy(pdp_type, "IPV6", sizeof(pdp_type));
|
||||
break;
|
||||
case IPV4V6_STACK:
|
||||
strncpy(pdp_type, "IPV6", sizeof(pdp_type)); // try first IPV6 and then fall-back to IPv4
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
//apn: "If the value is null or omitted, then the subscription value will be requested."
|
||||
bool success = false;
|
||||
_at.cmd_start("AT+CGDCONT=");
|
||||
_at.write_int(cid);
|
||||
_at.write_string(pdp_type);
|
||||
_at.write_string(_apn);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
success = (_at.get_last_error() == NSAPI_ERROR_OK);
|
||||
|
||||
// Fall back to ipv4
|
||||
if (!success && tmp_stack == IPV4V6_STACK) {
|
||||
_at.clear_error();
|
||||
tmp_stack = IPV4_STACK;
|
||||
_at.cmd_start("AT+FCLASS=0;+CGDCONT=");
|
||||
_at.write_int(cid);
|
||||
_at.write_string("IP");
|
||||
_at.write_string(_apn);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
success = (_at.get_last_error() == NSAPI_ERROR_OK);
|
||||
}
|
||||
|
||||
if (success) {
|
||||
_ip_stack_type = tmp_stack;
|
||||
_cid = cid;
|
||||
_new_context_set = true;
|
||||
tr_info("New PDP context id %d was created", _cid);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularContext::do_activate_context()
|
||||
{
|
||||
_at.lock();
|
||||
|
||||
nsapi_error_t err = NSAPI_ERROR_OK;
|
||||
|
||||
// try to find or create context with suitable stack
|
||||
if (get_context()) {
|
||||
#if NSAPI_PPP_AVAILABLE
|
||||
// in PPP we don't activate any context but leave it to PPP stack
|
||||
return err;
|
||||
#endif // NSAPI_PPP_AVAILABLE
|
||||
// try to authenticate user before activating or modifying context
|
||||
err = do_user_authentication();
|
||||
} else {
|
||||
err = NSAPI_ERROR_NO_CONNECTION;
|
||||
}
|
||||
|
||||
if (err != NSAPI_ERROR_OK) {
|
||||
_at.unlock();
|
||||
tr_error("Failed to activate network context! (%d)", err);
|
||||
call_network_cb(NSAPI_STATUS_DISCONNECTED);
|
||||
return err;
|
||||
}
|
||||
|
||||
// do check for stack to validate that we have support for stack
|
||||
if (!get_stack()) {
|
||||
tr_error("No cellular stack!");
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
_is_context_active = false;
|
||||
_is_context_activated = false;
|
||||
_at.cmd_start("AT+CGACT?");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start("+CGACT:");
|
||||
while (_at.info_resp()) {
|
||||
int context_id = _at.read_int();
|
||||
int context_activation_state = _at.read_int();
|
||||
if (context_id == _cid && context_activation_state == 1) {
|
||||
_is_context_active = true;
|
||||
}
|
||||
}
|
||||
_at.resp_stop();
|
||||
|
||||
if (!_is_context_active) {
|
||||
tr_info("Activate PDP context %d", _cid);
|
||||
_at.cmd_start("AT+CGACT=1,");
|
||||
_at.write_int(_cid);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
if (_at.get_last_error() == NSAPI_ERROR_OK) {
|
||||
_is_context_activated = true;
|
||||
}
|
||||
}
|
||||
|
||||
err = (_at.get_last_error() == NSAPI_ERROR_OK) ? NSAPI_ERROR_OK : NSAPI_ERROR_NO_CONNECTION;
|
||||
|
||||
// If new PDP context was created and failed to activate, delete it
|
||||
if (err != NSAPI_ERROR_OK && _new_context_set) {
|
||||
delete_current_context();
|
||||
} else if (err == NSAPI_ERROR_OK) {
|
||||
_is_context_active = true;
|
||||
}
|
||||
|
||||
_at.unlock();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void AT_CellularContext::do_connect()
|
||||
{
|
||||
call_network_cb(NSAPI_STATUS_CONNECTING);
|
||||
|
||||
if (!_is_context_active) {
|
||||
_cb_data.error = do_activate_context();
|
||||
#if !NSAPI_PPP_AVAILABLE
|
||||
// in PPP mode we did not activate any context, just searched the correct _cid
|
||||
if (_status_cb) {
|
||||
_status_cb((nsapi_event_t)CellularActivatePDPContext, (intptr_t )&_cb_data);
|
||||
}
|
||||
#endif // !NSAPI_PPP_AVAILABLE
|
||||
}
|
||||
|
||||
if (_cb_data.error != NSAPI_ERROR_OK) {
|
||||
call_network_cb(NSAPI_STATUS_DISCONNECTED);
|
||||
_is_connected = false;
|
||||
return;
|
||||
}
|
||||
#if NSAPI_PPP_AVAILABLE
|
||||
if (_cb_data.error == NSAPI_ERROR_OK) {
|
||||
_at.lock();
|
||||
_cb_data.error = open_data_channel();
|
||||
_at.unlock();
|
||||
if (_cb_data.error != NSAPI_ERROR_OK) {
|
||||
tr_error("Failed to open data channel!");
|
||||
call_network_cb(NSAPI_STATUS_DISCONNECTED);
|
||||
_is_connected = false;
|
||||
}
|
||||
}
|
||||
#else
|
||||
_is_connected = true;
|
||||
call_network_cb(NSAPI_STATUS_GLOBAL_UP);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if NSAPI_PPP_AVAILABLE
|
||||
nsapi_error_t AT_CellularContext::open_data_channel()
|
||||
{
|
||||
tr_info("Open data channel in PPP mode");
|
||||
if (is_supported(AT_CGDATA)) {
|
||||
_at.cmd_start("AT+CGDATA=\"PPP\",");
|
||||
_at.write_int(_cid);
|
||||
} else {
|
||||
MBED_ASSERT(_cid >= 0 && _cid <= 99);
|
||||
char cmd_buf[sizeof("ATD*99***xx#")];
|
||||
std::sprintf(cmd_buf, "ATD*99***%d#", _cid);
|
||||
_at.cmd_start(cmd_buf);
|
||||
}
|
||||
_at.cmd_stop();
|
||||
|
||||
_at.resp_start("CONNECT", true);
|
||||
if (_at.get_last_error()) {
|
||||
tr_error("Failed to CONNECT");
|
||||
return _at.get_last_error();
|
||||
}
|
||||
|
||||
_at.set_is_filehandle_usable(false);
|
||||
|
||||
/* Initialize PPP
|
||||
* If blocking: mbed_ppp_init() is a blocking call, it will block until
|
||||
connected, or timeout after 30 seconds*/
|
||||
return nsapi_ppp_connect(_at.get_file_handle(), callback(this, &AT_CellularContext::ppp_status_cb), _uname, _pwd, _ip_stack_type);
|
||||
}
|
||||
|
||||
void AT_CellularContext::ppp_status_cb(nsapi_event_t ev, intptr_t ptr)
|
||||
{
|
||||
if (ev == NSAPI_EVENT_CONNECTION_STATUS_CHANGE && ptr == NSAPI_STATUS_GLOBAL_UP) {
|
||||
_is_connected = true;
|
||||
} else {
|
||||
_is_connected = false;
|
||||
}
|
||||
|
||||
_connect_status = (nsapi_connection_status_t)ptr;
|
||||
|
||||
// call device's callback, it will broadcast this to here (cellular_callback)
|
||||
_device->cellular_callback(ev, ptr);
|
||||
}
|
||||
|
||||
#endif //#if NSAPI_PPP_AVAILABLE
|
||||
|
||||
nsapi_error_t AT_CellularContext::disconnect()
|
||||
{
|
||||
if (!_nw) {
|
||||
return NSAPI_ERROR_NO_CONNECTION;
|
||||
}
|
||||
#if NSAPI_PPP_AVAILABLE
|
||||
nsapi_error_t err = nsapi_ppp_disconnect(_at.get_file_handle());
|
||||
if (err != NSAPI_ERROR_OK) {
|
||||
tr_error("Cellular disconnect failed!");
|
||||
// continue even in failure due to ppp disconnect in any case releases filehandle
|
||||
}
|
||||
// after ppp disconnect if we wan't to use same at handler we need to set filehandle again to athandler so it
|
||||
// will set the correct sigio and nonblocking
|
||||
_at.lock();
|
||||
_at.set_file_handle(_at.get_file_handle());
|
||||
_at.set_is_filehandle_usable(true);
|
||||
//_at.sync(); // consume extra characters after ppp disconnect, also it may take a while until modem listens AT commands
|
||||
_at.unlock();
|
||||
#endif // NSAPI_PPP_AVAILABLE
|
||||
_at.lock();
|
||||
|
||||
// deactivate a context only if we have activated
|
||||
if (_is_context_activated) {
|
||||
_is_context_active = false;
|
||||
size_t active_contexts_count = 0;
|
||||
_at.cmd_start("AT+CGACT?");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start("+CGACT:");
|
||||
while (_at.info_resp()) {
|
||||
int context_id = _at.read_int();
|
||||
int context_activation_state = _at.read_int();
|
||||
if (context_activation_state == 1) {
|
||||
active_contexts_count++;
|
||||
if (context_id == _cid) {
|
||||
_is_context_active = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
_at.resp_stop();
|
||||
|
||||
CellularNetwork::RadioAccessTechnology rat = CellularNetwork::RAT_GSM;
|
||||
// always return NSAPI_ERROR_OK
|
||||
CellularNetwork::registration_params_t reg_params;
|
||||
_nw->get_registration_params(reg_params);
|
||||
rat = reg_params._act;
|
||||
// 3GPP TS 27.007:
|
||||
// For EPS, if an attempt is made to disconnect the last PDN connection, then the MT responds with ERROR
|
||||
if (_is_context_active && (rat < CellularNetwork::RAT_E_UTRAN || active_contexts_count > 1)) {
|
||||
_at.cmd_start("AT+CGACT=0,");
|
||||
_at.write_int(_cid);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
}
|
||||
}
|
||||
|
||||
if (!_at.get_last_error()) {
|
||||
call_network_cb(NSAPI_STATUS_DISCONNECTED);
|
||||
}
|
||||
|
||||
return _at.unlock_return_error();
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularContext::get_apn_backoff_timer(int &backoff_timer)
|
||||
{
|
||||
// If apn is set
|
||||
if (_apn) {
|
||||
_at.lock();
|
||||
_at.cmd_start("AT+CABTRDP=");
|
||||
_at.write_string(_apn);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start("+CABTRDP:");
|
||||
if (_at.info_resp()) {
|
||||
_at.skip_param();
|
||||
backoff_timer = _at.read_int();
|
||||
}
|
||||
_at.resp_stop();
|
||||
return _at.unlock_return_error();
|
||||
}
|
||||
|
||||
return NSAPI_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularContext::get_rate_control(
|
||||
CellularContext::RateControlExceptionReports &reports,
|
||||
CellularContext::RateControlUplinkTimeUnit &timeUnit, int &uplinkRate)
|
||||
{
|
||||
_at.lock();
|
||||
|
||||
_at.cmd_start("AT+CGAPNRC=");
|
||||
_at.write_int(_cid);
|
||||
_at.cmd_stop();
|
||||
|
||||
_at.resp_start("+CGAPNRC:");
|
||||
_at.read_int();
|
||||
if (_at.get_last_error() == NSAPI_ERROR_OK) {
|
||||
bool comma_found = true;
|
||||
int next_element = _at.read_int();
|
||||
if (next_element >= 0) {
|
||||
reports = (RateControlExceptionReports)next_element;
|
||||
tr_debug("reports %d", reports);
|
||||
next_element = _at.read_int();
|
||||
} else {
|
||||
comma_found = false;
|
||||
}
|
||||
|
||||
if (comma_found && next_element >= 0) {
|
||||
timeUnit = (RateControlUplinkTimeUnit)next_element;
|
||||
tr_debug("time %d", timeUnit);
|
||||
next_element = _at.read_int();
|
||||
} else {
|
||||
comma_found = false;
|
||||
}
|
||||
|
||||
if (comma_found && next_element >= 0) {
|
||||
uplinkRate = next_element;
|
||||
tr_debug("rate %d", uplinkRate);
|
||||
}
|
||||
}
|
||||
_at.resp_stop();
|
||||
|
||||
return _at.unlock_return_error();
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularContext::get_pdpcontext_params(pdpContextList_t ¶ms_list)
|
||||
{
|
||||
const int ipv6_subnet_size = 128;
|
||||
const int max_ipv6_size = 64;
|
||||
char *ipv6_and_subnetmask = (char *)malloc(ipv6_subnet_size);
|
||||
if (!ipv6_and_subnetmask) {
|
||||
return NSAPI_ERROR_NO_MEMORY;
|
||||
}
|
||||
|
||||
char *temp = (char *)malloc(max_ipv6_size);
|
||||
if (!temp) {
|
||||
free(ipv6_and_subnetmask);
|
||||
return NSAPI_ERROR_NO_MEMORY;
|
||||
}
|
||||
|
||||
_at.lock();
|
||||
|
||||
_at.cmd_start("AT+CGCONTRDP=");
|
||||
_at.write_int(_cid);
|
||||
_at.cmd_stop();
|
||||
|
||||
_at.resp_start("+CGCONTRDP:");
|
||||
pdpcontext_params_t *params = NULL;
|
||||
while (_at.info_resp()) { // response can be zero or many +CGDCONT lines
|
||||
params = params_list.add_new();
|
||||
if (!params) {
|
||||
tr_warn("Could not allocate new pdpcontext_params_t");
|
||||
_at.resp_stop();
|
||||
_at.unlock();
|
||||
params_list.delete_all();
|
||||
free(temp);
|
||||
free(ipv6_and_subnetmask);
|
||||
return NSAPI_ERROR_NO_MEMORY;
|
||||
}
|
||||
|
||||
params->cid = _at.read_int();
|
||||
params->bearer_id = _at.read_int();
|
||||
_at.read_string(params->apn, sizeof(params->apn));
|
||||
|
||||
// rest are optional params
|
||||
ipv6_and_subnetmask[0] = '\0';
|
||||
temp[0] = '\0';
|
||||
_at.read_string(ipv6_and_subnetmask, ipv6_subnet_size);
|
||||
separate_ip_addresses(ipv6_and_subnetmask, params->local_addr, sizeof(params->local_addr), params->local_subnet_mask, sizeof(params->local_subnet_mask));
|
||||
ipv6_and_subnetmask[0] = '\0';
|
||||
|
||||
_at.read_string(ipv6_and_subnetmask, ipv6_subnet_size);
|
||||
separate_ip_addresses(ipv6_and_subnetmask, params->gateway_addr, sizeof(params->gateway_addr), temp, max_ipv6_size);
|
||||
prefer_ipv6(params->gateway_addr, sizeof(params->gateway_addr), temp, max_ipv6_size);
|
||||
ipv6_and_subnetmask[0] = '\0';
|
||||
temp[0] = '\0';
|
||||
|
||||
_at.read_string(ipv6_and_subnetmask, ipv6_subnet_size);
|
||||
separate_ip_addresses(ipv6_and_subnetmask, params->dns_primary_addr, sizeof(params->dns_primary_addr), temp, max_ipv6_size);
|
||||
prefer_ipv6(params->dns_primary_addr, sizeof(params->dns_primary_addr), temp, max_ipv6_size);
|
||||
ipv6_and_subnetmask[0] = '\0';
|
||||
temp[0] = '\0';
|
||||
|
||||
_at.read_string(ipv6_and_subnetmask, ipv6_subnet_size);
|
||||
separate_ip_addresses(ipv6_and_subnetmask, params->dns_secondary_addr, sizeof(params->dns_secondary_addr), temp, max_ipv6_size);
|
||||
prefer_ipv6(params->dns_secondary_addr, sizeof(params->dns_secondary_addr), temp, max_ipv6_size);
|
||||
ipv6_and_subnetmask[0] = '\0';
|
||||
temp[0] = '\0';
|
||||
|
||||
_at.read_string(ipv6_and_subnetmask, ipv6_subnet_size);
|
||||
separate_ip_addresses(ipv6_and_subnetmask, params->p_cscf_prim_addr, sizeof(params->p_cscf_prim_addr), temp, max_ipv6_size);
|
||||
prefer_ipv6(params->p_cscf_prim_addr, sizeof(params->p_cscf_prim_addr), temp, max_ipv6_size);
|
||||
ipv6_and_subnetmask[0] = '\0';
|
||||
temp[0] = '\0';
|
||||
|
||||
_at.read_string(ipv6_and_subnetmask, ipv6_subnet_size);
|
||||
separate_ip_addresses(ipv6_and_subnetmask, params->p_cscf_sec_addr, sizeof(params->p_cscf_sec_addr), temp, max_ipv6_size);
|
||||
prefer_ipv6(params->p_cscf_sec_addr, sizeof(params->p_cscf_sec_addr), temp, max_ipv6_size);
|
||||
|
||||
params->im_signalling_flag = _at.read_int();
|
||||
params->lipa_indication = _at.read_int();
|
||||
params->ipv4_mtu = _at.read_int();
|
||||
params->wlan_offload = _at.read_int();
|
||||
params->local_addr_ind = _at.read_int();
|
||||
params->non_ip_mtu = _at.read_int();
|
||||
params->serving_plmn_rate_control_value = _at.read_int();
|
||||
}
|
||||
_at.resp_stop();
|
||||
|
||||
free(temp);
|
||||
free(ipv6_and_subnetmask);
|
||||
|
||||
return _at.unlock_return_error();
|
||||
}
|
||||
|
||||
// Called by CellularDevice for network and cellular device changes
|
||||
void AT_CellularContext::cellular_callback(nsapi_event_t ev, intptr_t ptr)
|
||||
{
|
||||
if (ev >= NSAPI_EVENT_CELLULAR_STATUS_BASE && ev <= NSAPI_EVENT_CELLULAR_STATUS_END) {
|
||||
cell_callback_data_t* data = (cell_callback_data_t*)ptr;
|
||||
cellular_connection_status_t st = (cellular_connection_status_t)ev;
|
||||
tr_debug("AT_CellularContext: network_callback called with event: %d, err: %d, data: %d", ev, data->error, data->status_data);
|
||||
_cb_data.error = data->error;
|
||||
|
||||
if (_is_blocking) {
|
||||
if (data->error != NSAPI_ERROR_OK) {
|
||||
// operation failed, release semaphore
|
||||
_semaphore.release();
|
||||
} else {
|
||||
if ((st == CellularDeviceReady && _current_op == OP_DEVICE_READY) ||
|
||||
(st == CellularSIMStatusChanged && _current_op == OP_SIM_READY &&
|
||||
data->status_data == CellularSIM::SimStateReady)) {
|
||||
// target reached, release semaphore
|
||||
_semaphore.release();
|
||||
} else if (st == CellularRegistrationStatusChanged && (data->status_data == CellularNetwork::RegisteredHomeNetwork ||
|
||||
data->status_data == CellularNetwork::RegisteredRoaming) && _current_op == OP_REGISTER) {
|
||||
// target reached, release semaphore
|
||||
_semaphore.release();
|
||||
} else if (st == CellularAttachNetwork && (_current_op == OP_ATTACH || _current_op == OP_CONNECT) &&
|
||||
data->status_data == CellularNetwork::Attached) {
|
||||
_nw = _device->open_network(_fh);
|
||||
// target reached, release semaphore
|
||||
_semaphore.release();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// non blocking
|
||||
if (st == CellularAttachNetwork && _current_op == OP_CONNECT && data->error == NSAPI_ERROR_OK &&
|
||||
data->status_data == CellularNetwork::Attached) {
|
||||
// forward to application
|
||||
if (_status_cb) {
|
||||
_status_cb(ev, ptr);
|
||||
}
|
||||
do_connect();
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tr_debug("AT_CellularContext: network_callback called with event: %d, ptr: %d", ev, ptr);
|
||||
#if NSAPI_PPP_AVAILABLE
|
||||
if (_is_blocking) {
|
||||
if (ev == NSAPI_EVENT_CONNECTION_STATUS_CHANGE && ptr == NSAPI_STATUS_GLOBAL_UP) {
|
||||
_cb_data.error = NSAPI_ERROR_OK;
|
||||
_semaphore.release();
|
||||
} else if (ev == NSAPI_EVENT_CONNECTION_STATUS_CHANGE && ptr == NSAPI_STATUS_DISCONNECTED) {
|
||||
_cb_data.error = NSAPI_ERROR_NO_CONNECTION;
|
||||
_semaphore.release();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// forward to application
|
||||
if (_status_cb) {
|
||||
_status_cb(ev, ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void AT_CellularContext::call_network_cb(nsapi_connection_status_t status)
|
||||
{
|
||||
if (_connect_status != status) {
|
||||
_connect_status = status;
|
||||
if (_status_cb) {
|
||||
_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, _connect_status);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef AT_CELLULARCONTEXT_H_
|
||||
#define AT_CELLULARCONTEXT_H_
|
||||
|
||||
#include "CellularContext.h"
|
||||
#include "AT_CellularBase.h"
|
||||
#include "Semaphore.h"
|
||||
|
||||
const int MAX_APN_LENGTH = 63 + 1;
|
||||
|
||||
namespace mbed {
|
||||
|
||||
class AT_CellularContext : public CellularContext, public AT_CellularBase {
|
||||
public:
|
||||
AT_CellularContext(ATHandler &at, CellularDevice *device, const char *apn = MBED_CONF_NSAPI_DEFAULT_CELLULAR_APN,
|
||||
nsapi_ip_stack_t stack = DEFAULT_STACK);
|
||||
virtual ~AT_CellularContext();
|
||||
|
||||
public: // from NetworkInterface
|
||||
virtual nsapi_error_t set_blocking(bool blocking);
|
||||
virtual NetworkStack *get_stack();
|
||||
virtual const char *get_ip_address();
|
||||
virtual void attach(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb);
|
||||
virtual nsapi_error_t connect();
|
||||
virtual nsapi_error_t disconnect();
|
||||
virtual bool is_connected();
|
||||
|
||||
public: // from CellularContext
|
||||
virtual nsapi_error_t get_pdpcontext_params(pdpContextList_t ¶ms_list);
|
||||
virtual nsapi_error_t get_rate_control(CellularContext::RateControlExceptionReports &reports,
|
||||
CellularContext::RateControlUplinkTimeUnit &time_unit, int &uplink_rate);
|
||||
virtual nsapi_error_t get_apn_backoff_timer(int &backoff_timer);
|
||||
virtual nsapi_error_t set_device_ready();
|
||||
virtual nsapi_error_t set_sim_ready();
|
||||
virtual nsapi_error_t register_to_network();
|
||||
virtual nsapi_error_t attach_to_network();
|
||||
virtual void set_apn_credentials(const char *uname = 0, const char *pwd = 0,
|
||||
CellularContext::AuthenticationType type = CellularContext::CHAP);
|
||||
virtual void set_apn_credentials(const char* apn, const char *uname = 0, const char *pwd = 0,
|
||||
CellularContext::AuthenticationType type = CellularContext::CHAP);
|
||||
virtual void set_file_handle(FileHandle *fh);
|
||||
|
||||
protected:
|
||||
virtual void cellular_callback(nsapi_event_t ev, intptr_t ptr);
|
||||
|
||||
/** Does the authentication for the PDP Context if user name and password are provided.
|
||||
* Can be overridden by the modem target if 3GPP default implementation if not an option
|
||||
*
|
||||
* @return NSAPI_ERROR_OK if no credentials provided or authentication was successful
|
||||
* NSAPI_ERROR_AUTH_FAILURE if authentication failed
|
||||
* NSAPI_ERROR_DEVICE_ERROR if communication with the modemm failed
|
||||
*/
|
||||
virtual nsapi_error_t do_user_authentication();
|
||||
|
||||
/** Activates PDP context or in PPP mode opens data channel.
|
||||
* Can be overridden by the modem target if 3GPP default implementation if not an option
|
||||
*/
|
||||
virtual void do_connect();
|
||||
|
||||
/** Check if modem supports the given stack type. Can be overridden by the modem.
|
||||
*
|
||||
* @return true if supported
|
||||
*/
|
||||
virtual bool stack_type_supported(nsapi_ip_stack_t stack_type);
|
||||
|
||||
/** Get the operation specific timeout. Used in synchronous mode when setting the maximum
|
||||
* waiting time. Modem specific implementation can override this to provide different timeouts.
|
||||
*
|
||||
* @param op current operation
|
||||
* @return timeout in milliseconds
|
||||
*/
|
||||
virtual uint32_t get_timeout_for_operation(ContextOperation op) const;
|
||||
|
||||
/** Helper method to call callback function if it is provided
|
||||
*
|
||||
* @param status connection status which is parameter in callback function
|
||||
*/
|
||||
void call_network_cb(nsapi_connection_status_t status);
|
||||
|
||||
private:
|
||||
#if NSAPI_PPP_AVAILABLE
|
||||
nsapi_error_t open_data_channel();
|
||||
void ppp_status_cb(nsapi_event_t ev, intptr_t ptr);
|
||||
#endif // #if NSAPI_PPP_AVAILABLE
|
||||
nsapi_error_t do_activate_context();
|
||||
bool set_new_context(int cid);
|
||||
bool get_context();
|
||||
nsapi_error_t delete_current_context();
|
||||
nsapi_ip_stack_t string_to_stack_type(const char *pdp_type);
|
||||
nsapi_ip_stack_t get_stack_type();
|
||||
nsapi_error_t check_operation(nsapi_error_t err, ContextOperation op);
|
||||
|
||||
private:
|
||||
nsapi_ip_stack_t _ip_stack_type_requested;
|
||||
bool _is_connected;
|
||||
bool _is_blocking;
|
||||
ContextOperation _current_op;
|
||||
char _found_apn[MAX_APN_LENGTH];
|
||||
CellularDevice *_device;
|
||||
CellularNetwork *_nw;
|
||||
FileHandle *_fh;
|
||||
rtos::Semaphore _semaphore;
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
||||
#endif // AT_CELLULARCONTEXT_H_
|
|
@ -21,7 +21,11 @@
|
|||
#include "AT_CellularPower.h"
|
||||
#include "AT_CellularSIM.h"
|
||||
#include "AT_CellularSMS.h"
|
||||
#include "AT_CellularContext.h"
|
||||
#include "AT_CellularStack.h"
|
||||
#include "CellularLog.h"
|
||||
#include "ATHandler.h"
|
||||
#include "UARTSerial.h"
|
||||
|
||||
using namespace events;
|
||||
using namespace mbed;
|
||||
|
@ -29,9 +33,10 @@ using namespace mbed;
|
|||
#define DEFAULT_AT_TIMEOUT 1000 // at default timeout in milliseconds
|
||||
|
||||
AT_CellularDevice::AT_CellularDevice(EventQueue &queue) :
|
||||
_atHandlers(0), _network(0), _sms(0), _sim(0), _power(0), _information(0), _at_queue(queue),
|
||||
_atHandlers(0), _network(0), _sms(0), _sim(0), _power(0), _information(0), _context_list(0), _at_queue(queue),
|
||||
_default_timeout(DEFAULT_AT_TIMEOUT), _modem_debug_on(false)
|
||||
{
|
||||
_fh = new UARTSerial(MDMTXD, MDMRXD, MBED_CONF_PLATFORM_DEFAULT_SERIAL_BAUD_RATE);
|
||||
}
|
||||
|
||||
AT_CellularDevice::~AT_CellularDevice()
|
||||
|
@ -49,12 +54,22 @@ AT_CellularDevice::~AT_CellularDevice()
|
|||
close_sim();
|
||||
close_information();
|
||||
|
||||
AT_CellularContext* curr = _context_list;
|
||||
AT_CellularContext* next;
|
||||
while (curr) {
|
||||
next = (AT_CellularContext*)curr->_next;
|
||||
delete curr;
|
||||
curr = next;
|
||||
}
|
||||
|
||||
ATHandler *atHandler = _atHandlers;
|
||||
while (atHandler) {
|
||||
ATHandler *old = atHandler;
|
||||
atHandler = atHandler->_nextATHandler;
|
||||
delete old;
|
||||
}
|
||||
|
||||
delete _fh;
|
||||
}
|
||||
|
||||
events::EventQueue *AT_CellularDevice::get_queue() const
|
||||
|
@ -66,7 +81,7 @@ events::EventQueue *AT_CellularDevice::get_queue() const
|
|||
ATHandler *AT_CellularDevice::get_at_handler(FileHandle *fileHandle)
|
||||
{
|
||||
if (!fileHandle) {
|
||||
return NULL;
|
||||
fileHandle = _fh;
|
||||
}
|
||||
ATHandler *atHandler = _atHandlers;
|
||||
while (atHandler) {
|
||||
|
@ -114,6 +129,58 @@ void AT_CellularDevice::release_at_handler(ATHandler *at_handler)
|
|||
}
|
||||
}
|
||||
|
||||
CellularContext *AT_CellularDevice::get_context_list() const
|
||||
{
|
||||
return _context_list;
|
||||
}
|
||||
|
||||
CellularContext *AT_CellularDevice::create_context(FileHandle *fh, const char *apn, nsapi_ip_stack_t stack)
|
||||
{
|
||||
ATHandler *atHandler = get_at_handler(_fh);
|
||||
if (atHandler) {
|
||||
AT_CellularContext *ctx = create_context_impl(*atHandler, apn, stack);
|
||||
AT_CellularContext* curr = _context_list;
|
||||
|
||||
if (_context_list == NULL) {
|
||||
_context_list = ctx;
|
||||
return ctx;
|
||||
}
|
||||
|
||||
AT_CellularContext* prev;
|
||||
while (curr) {
|
||||
prev = curr;
|
||||
curr = (AT_CellularContext*)curr->_next;
|
||||
}
|
||||
|
||||
prev->_next = ctx;
|
||||
return ctx;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
AT_CellularContext *AT_CellularDevice::create_context_impl(ATHandler &at, const char *apn, nsapi_ip_stack_t stack)
|
||||
{
|
||||
return new AT_CellularContext(at, this, apn, stack);
|
||||
}
|
||||
|
||||
void AT_CellularDevice::delete_context(CellularContext *context)
|
||||
{
|
||||
AT_CellularContext* curr = _context_list;
|
||||
AT_CellularContext* prev = NULL;
|
||||
while (curr) {
|
||||
if (curr == context) {
|
||||
if (prev == NULL) {
|
||||
_context_list = (AT_CellularContext*)curr->_next;
|
||||
} else {
|
||||
prev->_next = curr->_next;
|
||||
}
|
||||
}
|
||||
prev = curr;
|
||||
curr = (AT_CellularContext*)curr->_next;
|
||||
}
|
||||
delete (AT_CellularContext*)context;
|
||||
}
|
||||
|
||||
CellularNetwork *AT_CellularDevice::open_network(FileHandle *fh)
|
||||
{
|
||||
if (!_network) {
|
||||
|
@ -301,14 +368,6 @@ void AT_CellularDevice::modem_debug_on(bool on)
|
|||
}
|
||||
}
|
||||
|
||||
NetworkStack *AT_CellularDevice::get_stack()
|
||||
{
|
||||
if (!_network) {
|
||||
return NULL;
|
||||
}
|
||||
return _network->get_stack();
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularDevice::init_module(FileHandle *fh)
|
||||
{
|
||||
return NSAPI_ERROR_OK;
|
||||
|
|
|
@ -28,6 +28,7 @@ class AT_CellularNetwork;
|
|||
class AT_CellularPower;
|
||||
class AT_CellularSIM;
|
||||
class AT_CellularSMS;
|
||||
class AT_CellularContext;
|
||||
|
||||
/**
|
||||
* Class AT_CellularDevice
|
||||
|
@ -54,15 +55,19 @@ public: // CellularDevice
|
|||
|
||||
virtual events::EventQueue *get_queue() const;
|
||||
|
||||
virtual CellularNetwork *open_network(FileHandle *fh);
|
||||
virtual CellularContext *create_context(FileHandle *fh = NULL, const char *apn = MBED_CONF_NSAPI_DEFAULT_CELLULAR_APN, nsapi_ip_stack_t stack = DEFAULT_STACK);
|
||||
|
||||
virtual CellularSMS *open_sms(FileHandle *fh);
|
||||
virtual void delete_context(CellularContext *context);
|
||||
|
||||
virtual CellularPower *open_power(FileHandle *fh);
|
||||
virtual CellularNetwork *open_network(FileHandle *fh = NULL);
|
||||
|
||||
virtual CellularSIM *open_sim(FileHandle *fh);
|
||||
virtual CellularSMS *open_sms(FileHandle *fh = NULL);
|
||||
|
||||
virtual CellularInformation *open_information(FileHandle *fh);
|
||||
virtual CellularPower *open_power(FileHandle *fh = NULL);
|
||||
|
||||
virtual CellularSIM *open_sim(FileHandle *fh = NULL);
|
||||
|
||||
virtual CellularInformation *open_information(FileHandle *fh = NULL);
|
||||
|
||||
virtual void close_network();
|
||||
|
||||
|
@ -80,11 +85,12 @@ public: // CellularDevice
|
|||
|
||||
virtual void modem_debug_on(bool on);
|
||||
|
||||
virtual NetworkStack *get_stack();
|
||||
|
||||
virtual nsapi_error_t init_module(FileHandle *fh);
|
||||
|
||||
protected:
|
||||
|
||||
virtual AT_CellularContext *create_context_impl(ATHandler &at, const char *apn, nsapi_ip_stack_t stack);
|
||||
|
||||
/** Create new instance of AT_CellularNetwork or if overridden, modem specific implementation.
|
||||
*
|
||||
* @param at ATHandler reference for communication with the modem.
|
||||
|
@ -120,12 +126,14 @@ protected:
|
|||
*/
|
||||
virtual AT_CellularInformation *open_information_impl(ATHandler &at);
|
||||
|
||||
virtual CellularContext *get_context_list() const;
|
||||
|
||||
AT_CellularNetwork *_network;
|
||||
AT_CellularSMS *_sms;
|
||||
AT_CellularSIM *_sim;
|
||||
AT_CellularPower *_power;
|
||||
AT_CellularInformation *_information;
|
||||
|
||||
AT_CellularContext *_context_list;
|
||||
protected:
|
||||
events::EventQueue &_at_queue;
|
||||
int _default_timeout;
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
#include "AT_CellularNetwork.h"
|
||||
#include "nsapi_ppp.h"
|
||||
#include "CellularUtil.h"
|
||||
#include "CellularLog.h"
|
||||
#include "CellularCommon.h"
|
||||
|
@ -39,65 +38,47 @@ static const at_reg_t at_reg[] = {
|
|||
};
|
||||
|
||||
AT_CellularNetwork::AT_CellularNetwork(ATHandler &atHandler) : AT_CellularBase(atHandler),
|
||||
_stack(NULL), _apn(NULL), _uname(NULL), _pwd(NULL), _ip_stack_type_requested(DEFAULT_STACK),
|
||||
_ip_stack_type(DEFAULT_STACK), _cid(-1), _connection_status_cb(NULL), _op_act(RAT_UNKNOWN),
|
||||
_authentication_type(CHAP), _connect_status(NSAPI_STATUS_DISCONNECTED), _new_context_set(false),
|
||||
_is_context_active(false)
|
||||
_connection_status_cb(NULL), _op_act(RAT_UNKNOWN), _connect_status(NSAPI_STATUS_DISCONNECTED)
|
||||
{
|
||||
}
|
||||
|
||||
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) != RegistrationModeDisable) {
|
||||
_at.remove_urc_handler(at_reg[type].urc_prefix);
|
||||
}
|
||||
}
|
||||
|
||||
_at.remove_urc_handler("NO CARRIER");
|
||||
_at.remove_urc_handler("+CGEV:");
|
||||
free_credentials();
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::init()
|
||||
{
|
||||
_urc_funcs[C_EREG] = callback(this, &AT_CellularNetwork::urc_cereg);
|
||||
_urc_funcs[C_GREG] = callback(this, &AT_CellularNetwork::urc_cgreg);
|
||||
_urc_funcs[C_REG] = callback(this, &AT_CellularNetwork::urc_creg);
|
||||
|
||||
for (int type = 0; type < CellularNetwork::C_MAX; type++) {
|
||||
if (has_registration((RegistrationType)type) != RegistrationModeDisable) {
|
||||
if (_at.set_urc_handler(at_reg[type].urc_prefix, _urc_funcs[type]) != NSAPI_ERROR_OK) {
|
||||
return NSAPI_ERROR_NO_MEMORY;
|
||||
}
|
||||
_at.set_urc_handler(at_reg[type].urc_prefix, _urc_funcs[type]);
|
||||
}
|
||||
}
|
||||
|
||||
return _at.set_urc_handler("NO CARRIER", callback(this, &AT_CellularNetwork::urc_no_carrier));
|
||||
_at.set_urc_handler("NO CARRIER", callback(this, &AT_CellularNetwork::urc_no_carrier));
|
||||
// additional urc to get better disconnect info for application. Not critical.
|
||||
_at.set_urc_handler("+CGEV:", callback(this, &AT_CellularNetwork::urc_cgev));
|
||||
_at.lock();
|
||||
_at.cmd_start("AT+CGEREP=1");// discard unsolicited result codes when MT TE link is reserved (e.g. in on line data mode); otherwise forward them directly to the TE
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
_at.unlock();
|
||||
}
|
||||
|
||||
void AT_CellularNetwork::free_credentials()
|
||||
AT_CellularNetwork::~AT_CellularNetwork()
|
||||
{
|
||||
if (_uname) {
|
||||
free(_uname);
|
||||
_uname = NULL;
|
||||
_at.lock();
|
||||
_at.cmd_start("AT+CGEREP=0");// buffer unsolicited result codes in the MT; if MT result code buffer is full, the oldest ones can be discarded. No codes are forwarded to the TE
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
_at.unlock();
|
||||
|
||||
for (int type = 0; type < CellularNetwork::C_MAX; type++) {
|
||||
if (has_registration((RegistrationType)type) != RegistrationModeDisable) {
|
||||
_at.remove_urc_handler(at_reg[type].urc_prefix, _urc_funcs[type]);
|
||||
}
|
||||
}
|
||||
|
||||
if (_pwd) {
|
||||
free(_pwd);
|
||||
_pwd = NULL;
|
||||
}
|
||||
|
||||
if (_apn) {
|
||||
free(_apn);
|
||||
_apn = NULL;
|
||||
}
|
||||
_at.remove_urc_handler("NO CARRIER", callback(this, &AT_CellularNetwork::urc_no_carrier));
|
||||
_at.remove_urc_handler("+CGEV:", callback(this, &AT_CellularNetwork::urc_cgev));
|
||||
}
|
||||
|
||||
void AT_CellularNetwork::urc_no_carrier()
|
||||
|
@ -160,21 +141,21 @@ void AT_CellularNetwork::read_reg_params_and_compare(RegistrationType type)
|
|||
if (_at.get_last_error() == NSAPI_ERROR_OK && _connection_status_cb) {
|
||||
tr_debug("type: %d, status: %d, lac: %d, cellID: %d, act: %d", type, reg_params._status, reg_params._lac, reg_params._cell_id, reg_params._act);
|
||||
_reg_params._type = type;
|
||||
cell_callback_data_t data;
|
||||
cell_callback_data_t data;
|
||||
data.error = NSAPI_ERROR_OK;
|
||||
if (reg_params._act != _reg_params._act) {
|
||||
_reg_params._act = reg_params._act;
|
||||
data.status_data = reg_params._act;
|
||||
data.status_data = reg_params._act;
|
||||
_connection_status_cb((nsapi_event_t)CellularRadioAccessTechnologyChanged, (intptr_t)&data);
|
||||
}
|
||||
if (reg_params._status != _reg_params._status) {
|
||||
_reg_params._status = reg_params._status;
|
||||
data.status_data = reg_params._status;
|
||||
data.status_data = reg_params._status;
|
||||
_connection_status_cb((nsapi_event_t)CellularRegistrationStatusChanged, (intptr_t)&data);
|
||||
}
|
||||
if (reg_params._cell_id != -1 && reg_params._cell_id != _reg_params._cell_id) {
|
||||
_reg_params._cell_id = reg_params._cell_id;
|
||||
data.status_data = reg_params._cell_id;
|
||||
data.status_data = reg_params._cell_id;
|
||||
_connection_status_cb((nsapi_event_t)CellularCellIDChanged, (intptr_t)&data);
|
||||
}
|
||||
}
|
||||
|
@ -198,278 +179,6 @@ void AT_CellularNetwork::urc_cgreg()
|
|||
read_reg_params_and_compare(C_GREG);
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::set_credentials(const char *apn,
|
||||
const char *username, const char *password)
|
||||
{
|
||||
free_credentials();
|
||||
|
||||
size_t len;
|
||||
if (apn && (len = strlen(apn)) > 0) {
|
||||
_apn = (char *)malloc(len * sizeof(char) + 1);
|
||||
if (_apn) {
|
||||
memcpy(_apn, apn, len + 1);
|
||||
} else {
|
||||
return NSAPI_ERROR_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
if (username && (len = strlen(username)) > 0) {
|
||||
if (!is_supported(AT_CGAUTH)) { // APN authentication is needed with username/password
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
_uname = (char *)malloc(len * sizeof(char) + 1);
|
||||
if (_uname) {
|
||||
memcpy(_uname, username, len + 1);
|
||||
} else {
|
||||
return NSAPI_ERROR_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
if (password && (len = strlen(password)) > 0) {
|
||||
_pwd = (char *)malloc(len * sizeof(char) + 1);
|
||||
if (_pwd) {
|
||||
memcpy(_pwd, password, len + 1);
|
||||
} else {
|
||||
return NSAPI_ERROR_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::set_credentials(const char *apn,
|
||||
AuthenticationType type, const char *username, const char *password)
|
||||
{
|
||||
nsapi_error_t err = set_credentials(apn, username, password);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
_authentication_type = type;
|
||||
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::connect(const char *apn,
|
||||
const char *username, const char *password)
|
||||
{
|
||||
nsapi_error_t err = set_credentials(apn, username, password);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return connect();
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::delete_current_context()
|
||||
{
|
||||
tr_info("Delete context %d", _cid);
|
||||
_at.clear_error();
|
||||
_at.cmd_start("AT+CGDCONT=");
|
||||
_at.write_int(_cid);
|
||||
_at.cmd_stop_read_resp();
|
||||
|
||||
if (_at.get_last_error() == NSAPI_ERROR_OK) {
|
||||
_cid = -1;
|
||||
_new_context_set = false;
|
||||
}
|
||||
|
||||
return _at.get_last_error();
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::activate_context()
|
||||
{
|
||||
_at.lock();
|
||||
|
||||
nsapi_error_t err = NSAPI_ERROR_OK;
|
||||
|
||||
// try to find or create context with suitable stack
|
||||
if (!get_context()) {
|
||||
err = NSAPI_ERROR_NO_CONNECTION;
|
||||
}
|
||||
|
||||
if (err != NSAPI_ERROR_OK) {
|
||||
_at.unlock();
|
||||
tr_error("Failed to activate network context! (%d)", err);
|
||||
call_network_cb(NSAPI_STATUS_DISCONNECTED);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
// do check for stack to validate that we have support for stack
|
||||
_stack = get_stack();
|
||||
if (!_stack) {
|
||||
tr_error("No cellular stack!");
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
_is_context_active = false;
|
||||
_at.cmd_start("AT+CGACT?");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start("+CGACT:");
|
||||
while (_at.info_resp()) {
|
||||
int context_id = _at.read_int();
|
||||
int context_activation_state = _at.read_int();
|
||||
if (context_id == _cid && context_activation_state == 1) {
|
||||
_is_context_active = true;
|
||||
}
|
||||
}
|
||||
_at.resp_stop();
|
||||
|
||||
if (!_is_context_active) {
|
||||
// authenticate before activating or modifying context
|
||||
nsapi_error_t err = do_user_authentication();
|
||||
if (err != NSAPI_ERROR_OK) {
|
||||
tr_error("Cellular authentication failed!");
|
||||
return err;
|
||||
}
|
||||
|
||||
tr_info("Activate PDP context %d", _cid);
|
||||
_at.cmd_start("AT+CGACT=1,");
|
||||
_at.write_int(_cid);
|
||||
_at.cmd_stop_read_resp();
|
||||
}
|
||||
|
||||
err = (_at.get_last_error() == NSAPI_ERROR_OK) ? NSAPI_ERROR_OK : NSAPI_ERROR_NO_CONNECTION;
|
||||
|
||||
// If new PDP context was created and failed to activate, delete it
|
||||
if (err != NSAPI_ERROR_OK && _new_context_set) {
|
||||
delete_current_context();
|
||||
} else if (err == NSAPI_ERROR_OK) {
|
||||
_is_context_active = true;
|
||||
}
|
||||
|
||||
_at.unlock();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::connect()
|
||||
{
|
||||
call_network_cb(NSAPI_STATUS_CONNECTING);
|
||||
|
||||
nsapi_error_t err = NSAPI_ERROR_OK;
|
||||
if (!_is_context_active) {
|
||||
err = activate_context();
|
||||
}
|
||||
if (err) {
|
||||
call_network_cb(NSAPI_STATUS_DISCONNECTED);
|
||||
return err;
|
||||
}
|
||||
|
||||
#if NSAPI_PPP_AVAILABLE
|
||||
_at.lock();
|
||||
err = open_data_channel();
|
||||
_at.unlock();
|
||||
if (err != NSAPI_ERROR_OK) {
|
||||
tr_error("Failed to open data channel!");
|
||||
call_network_cb(NSAPI_STATUS_DISCONNECTED);
|
||||
return err;
|
||||
}
|
||||
#else
|
||||
// additional urc to get better disconnect info for application. Not critical so not returning an error in case of failure
|
||||
err = _at.set_urc_handler("+CGEV:", callback(this, &AT_CellularNetwork::urc_cgev));
|
||||
if (err == NSAPI_ERROR_OK) {
|
||||
_at.lock();
|
||||
_at.cmd_start("AT+CGEREP=1");
|
||||
_at.cmd_stop_read_resp();
|
||||
_at.unlock();
|
||||
}
|
||||
|
||||
call_network_cb(NSAPI_STATUS_GLOBAL_UP);
|
||||
#endif
|
||||
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::open_data_channel()
|
||||
{
|
||||
#if NSAPI_PPP_AVAILABLE
|
||||
tr_info("Open data channel in PPP mode");
|
||||
if (is_supported(AT_CGDATA)) {
|
||||
_at.cmd_start("AT+CGDATA=\"PPP\",");
|
||||
_at.write_int(_cid);
|
||||
} else {
|
||||
MBED_ASSERT(_cid >= 0 && _cid <= 99);
|
||||
_at.cmd_start("ATD*99***");
|
||||
_at.use_delimiter(false);
|
||||
_at.write_int(_cid);
|
||||
_at.write_string("#", false);
|
||||
_at.use_delimiter(true);
|
||||
}
|
||||
_at.cmd_stop();
|
||||
|
||||
_at.resp_start("CONNECT", true);
|
||||
if (_at.get_last_error()) {
|
||||
tr_error("Failed to CONNECT");
|
||||
return _at.get_last_error();
|
||||
}
|
||||
|
||||
_at.set_is_filehandle_usable(false);
|
||||
|
||||
/* Initialize PPP
|
||||
* If blocking: mbed_ppp_init() is a blocking call, it will block until
|
||||
connected, or timeout after 30 seconds*/
|
||||
return nsapi_ppp_connect(_at.get_file_handle(), callback(this, &AT_CellularNetwork::ppp_status_cb), NULL, NULL, _ip_stack_type);
|
||||
#else
|
||||
return NSAPI_ERROR_OK;
|
||||
#endif // #if NSAPI_PPP_AVAILABLE
|
||||
}
|
||||
|
||||
/**
|
||||
* User initiated disconnect
|
||||
*
|
||||
* Disconnects from PPP connection only and brings down the underlying network
|
||||
* interface
|
||||
*/
|
||||
nsapi_error_t AT_CellularNetwork::disconnect()
|
||||
{
|
||||
#if NSAPI_PPP_AVAILABLE
|
||||
nsapi_error_t err = nsapi_ppp_disconnect(_at.get_file_handle());
|
||||
// after ppp disconnect if we wan't to use same at handler we need to set filehandle again to athandler so it
|
||||
// will set the correct sigio and nonblocking
|
||||
_at.lock();
|
||||
_at.set_file_handle(_at.get_file_handle());
|
||||
_at.set_is_filehandle_usable(true);
|
||||
_at.unlock();
|
||||
return err;
|
||||
#else
|
||||
_at.lock();
|
||||
|
||||
_is_context_active = false;
|
||||
size_t active_contexts_count = 0;
|
||||
_at.cmd_start("AT+CGACT?");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start("+CGACT:");
|
||||
while (_at.info_resp()) {
|
||||
int context_id = _at.read_int();
|
||||
int context_activation_state = _at.read_int();
|
||||
if (context_activation_state == 1) {
|
||||
active_contexts_count++;
|
||||
if (context_id == _cid) {
|
||||
_is_context_active = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
_at.resp_stop();
|
||||
|
||||
// 3GPP TS 27.007:
|
||||
// For EPS, if an attempt is made to disconnect the last PDN connection, then the MT responds with ERROR
|
||||
if (_is_context_active && (_reg_params._act < RAT_E_UTRAN || active_contexts_count > 1)) {
|
||||
_at.cmd_start("AT+CGACT=0,");
|
||||
_at.write_int(_cid);
|
||||
_at.cmd_stop_read_resp();
|
||||
}
|
||||
|
||||
_at.restore_at_timeout();
|
||||
|
||||
_at.remove_urc_handler("+CGEV:");
|
||||
call_network_cb(NSAPI_STATUS_DISCONNECTED);
|
||||
|
||||
return _at.unlock_return_error();
|
||||
#endif
|
||||
}
|
||||
|
||||
void AT_CellularNetwork::call_network_cb(nsapi_connection_status_t status)
|
||||
{
|
||||
if (_connect_status != status) {
|
||||
|
@ -490,224 +199,6 @@ nsapi_connection_status_t AT_CellularNetwork::get_connection_status() const
|
|||
return _connect_status;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::set_blocking(bool blocking)
|
||||
{
|
||||
#if NSAPI_PPP_AVAILABLE
|
||||
return nsapi_ppp_set_blocking(blocking);
|
||||
#else
|
||||
return NSAPI_ERROR_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if NSAPI_PPP_AVAILABLE
|
||||
void AT_CellularNetwork::ppp_status_cb(nsapi_event_t event, intptr_t parameter)
|
||||
{
|
||||
_connect_status = (nsapi_connection_status_t)parameter;
|
||||
|
||||
if (_connection_status_cb) {
|
||||
_connection_status_cb(event, parameter);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::do_user_authentication()
|
||||
{
|
||||
// if user has defined user name and password we need to call CGAUTH before activating or modifying context
|
||||
if (_pwd && _uname) {
|
||||
if (!is_supported(AT_CGAUTH)) {
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
_at.cmd_start("AT+CGAUTH=");
|
||||
_at.write_int(_cid);
|
||||
_at.write_int(_authentication_type);
|
||||
_at.write_string(_uname);
|
||||
_at.write_string(_pwd);
|
||||
_at.cmd_stop_read_resp();
|
||||
if (_at.get_last_error() != NSAPI_ERROR_OK) {
|
||||
return NSAPI_ERROR_AUTH_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
bool AT_CellularNetwork::set_new_context(int cid)
|
||||
{
|
||||
nsapi_ip_stack_t tmp_stack = _ip_stack_type_requested;
|
||||
|
||||
if (tmp_stack == DEFAULT_STACK) {
|
||||
bool modem_supports_ipv6 = get_modem_stack_type(IPV6_STACK);
|
||||
bool modem_supports_ipv4 = get_modem_stack_type(IPV4_STACK);
|
||||
|
||||
if (modem_supports_ipv6 && modem_supports_ipv4) {
|
||||
tmp_stack = IPV4V6_STACK;
|
||||
} else if (modem_supports_ipv6) {
|
||||
tmp_stack = IPV6_STACK;
|
||||
} else if (modem_supports_ipv4) {
|
||||
tmp_stack = IPV4_STACK;
|
||||
}
|
||||
}
|
||||
|
||||
char pdp_type[8 + 1] = {0};
|
||||
|
||||
switch (tmp_stack) {
|
||||
case IPV4_STACK:
|
||||
strncpy(pdp_type, "IP", sizeof(pdp_type));
|
||||
break;
|
||||
case IPV6_STACK:
|
||||
strncpy(pdp_type, "IPV6", sizeof(pdp_type));
|
||||
break;
|
||||
case IPV4V6_STACK:
|
||||
strncpy(pdp_type, "IPV6", sizeof(pdp_type)); // try first IPV6 and then fall-back to IPv4
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
//apn: "If the value is null or omitted, then the subscription value will be requested."
|
||||
bool success = false;
|
||||
_at.cmd_start("AT+CGDCONT=");
|
||||
_at.write_int(cid);
|
||||
_at.write_string(pdp_type);
|
||||
_at.write_string(_apn);
|
||||
_at.cmd_stop_read_resp();
|
||||
success = (_at.get_last_error() == NSAPI_ERROR_OK);
|
||||
|
||||
// Fall back to ipv4
|
||||
if (!success && tmp_stack == IPV4V6_STACK) {
|
||||
tmp_stack = IPV4_STACK;
|
||||
_at.clear_error();
|
||||
_at.cmd_start("AT+FCLASS=0;+CGDCONT=");
|
||||
_at.write_int(cid);
|
||||
_at.write_string("IP");
|
||||
_at.write_string(_apn);
|
||||
_at.cmd_stop_read_resp();
|
||||
success = (_at.get_last_error() == NSAPI_ERROR_OK);
|
||||
}
|
||||
|
||||
if (success) {
|
||||
_ip_stack_type = tmp_stack;
|
||||
_cid = cid;
|
||||
_new_context_set = true;
|
||||
tr_info("New PDP context id %d was created", _cid);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool AT_CellularNetwork::get_context()
|
||||
{
|
||||
if (_apn) {
|
||||
tr_debug("APN in use: %s", _apn);
|
||||
} else {
|
||||
tr_debug("NO APN");
|
||||
}
|
||||
|
||||
_at.cmd_start("AT+CGDCONT?");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start("+CGDCONT:");
|
||||
_cid = -1;
|
||||
int cid_max = 0; // needed when creating new context
|
||||
char apn[MAX_ACCESSPOINT_NAME_LENGTH];
|
||||
int apn_len = 0;
|
||||
|
||||
bool modem_supports_ipv6 = get_modem_stack_type(IPV6_STACK);
|
||||
bool modem_supports_ipv4 = get_modem_stack_type(IPV4_STACK);
|
||||
|
||||
while (_at.info_resp()) {
|
||||
int cid = _at.read_int();
|
||||
if (cid > cid_max) {
|
||||
cid_max = cid;
|
||||
}
|
||||
char pdp_type_from_context[10];
|
||||
int pdp_type_len = _at.read_string(pdp_type_from_context, sizeof(pdp_type_from_context) - 1);
|
||||
if (pdp_type_len > 0) {
|
||||
apn_len = _at.read_string(apn, sizeof(apn) - 1);
|
||||
if (apn_len >= 0) {
|
||||
if (_apn && (strcmp(apn, _apn) != 0)) {
|
||||
continue;
|
||||
}
|
||||
nsapi_ip_stack_t pdp_stack = string_to_stack_type(pdp_type_from_context);
|
||||
// Accept dual PDP context for IPv4/IPv6 only modems
|
||||
if (pdp_stack != DEFAULT_STACK && (get_modem_stack_type(pdp_stack) || pdp_stack == IPV4V6_STACK)) {
|
||||
if (_ip_stack_type_requested == IPV4_STACK) {
|
||||
if (pdp_stack == IPV4_STACK || pdp_stack == IPV4V6_STACK) {
|
||||
_ip_stack_type = _ip_stack_type_requested;
|
||||
_cid = cid;
|
||||
break;
|
||||
}
|
||||
} else if (_ip_stack_type_requested == IPV6_STACK) {
|
||||
if (pdp_stack == IPV6_STACK || pdp_stack == IPV4V6_STACK) {
|
||||
_ip_stack_type = _ip_stack_type_requested;
|
||||
_cid = cid;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// requested dual stack or stack is not specified
|
||||
// If dual PDP need to check for IPV4 or IPV6 modem support. Prefer IPv6.
|
||||
if (pdp_stack == IPV4V6_STACK) {
|
||||
if (modem_supports_ipv6) {
|
||||
_ip_stack_type = IPV6_STACK;
|
||||
_cid = cid;
|
||||
break;
|
||||
} else if (modem_supports_ipv4) {
|
||||
_ip_stack_type = IPV4_STACK;
|
||||
_cid = cid;
|
||||
break;
|
||||
}
|
||||
// If PDP is IPV4 or IPV6 they are already checked if supported
|
||||
} else {
|
||||
_ip_stack_type = pdp_stack;
|
||||
_cid = cid;
|
||||
|
||||
if (pdp_stack == IPV6_STACK) {
|
||||
break;
|
||||
}
|
||||
if (pdp_stack == IPV4_STACK && !modem_supports_ipv6) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_at.resp_stop();
|
||||
if (_cid == -1) { // no suitable context was found so create a new one
|
||||
if (!set_new_context(cid_max + 1)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// save the apn
|
||||
if (apn_len > 0 && !_apn) {
|
||||
_apn = (char *)malloc(apn_len * sizeof(char) + 1);
|
||||
if (_apn) {
|
||||
memcpy(_apn, apn, apn_len + 1);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
tr_debug("Context id %d", _cid);
|
||||
return true;
|
||||
}
|
||||
|
||||
nsapi_ip_stack_t AT_CellularNetwork::string_to_stack_type(const char *pdp_type)
|
||||
{
|
||||
nsapi_ip_stack_t stack = DEFAULT_STACK;
|
||||
int len = strlen(pdp_type);
|
||||
|
||||
if (len == 6 && memcmp(pdp_type, "IPV4V6", len) == 0) {
|
||||
stack = IPV4V6_STACK;
|
||||
} else if (len == 4 && memcmp(pdp_type, "IPV6", len) == 0) {
|
||||
stack = IPV6_STACK;
|
||||
} else if (len == 2 && memcmp(pdp_type, "IP", len) == 0) {
|
||||
stack = IPV4_STACK;
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::set_registration_urc(RegistrationType type, bool urc_on)
|
||||
{
|
||||
int index = (int)type;
|
||||
|
@ -820,7 +311,7 @@ AT_CellularNetwork::RegistrationMode AT_CellularNetwork::has_registration(Regist
|
|||
return RegistrationModeLAC;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::set_attach(int /*timeout*/)
|
||||
nsapi_error_t AT_CellularNetwork::set_attach()
|
||||
{
|
||||
_at.lock();
|
||||
|
||||
|
@ -868,76 +359,6 @@ nsapi_error_t AT_CellularNetwork::detach()
|
|||
return _at.unlock_return_error();
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::get_apn_backoff_timer(int &backoff_timer)
|
||||
{
|
||||
// If apn is set
|
||||
if (_apn) {
|
||||
_at.lock();
|
||||
_at.cmd_start("AT+CABTRDP=");
|
||||
_at.write_string(_apn);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start("+CABTRDP:");
|
||||
if (_at.info_resp()) {
|
||||
_at.skip_param();
|
||||
backoff_timer = _at.read_int();
|
||||
}
|
||||
_at.resp_stop();
|
||||
return _at.unlock_return_error();
|
||||
}
|
||||
|
||||
return NSAPI_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
NetworkStack *AT_CellularNetwork::get_stack()
|
||||
{
|
||||
#if NSAPI_PPP_AVAILABLE
|
||||
// use lwIP/PPP if modem does not have IP stack
|
||||
if (!_stack) {
|
||||
_stack = nsapi_ppp_get_stack();
|
||||
}
|
||||
#endif
|
||||
return _stack;
|
||||
}
|
||||
|
||||
const char *AT_CellularNetwork::get_ip_address()
|
||||
{
|
||||
#if NSAPI_PPP_AVAILABLE
|
||||
return nsapi_ppp_get_ip_addr(_at.get_file_handle());
|
||||
#else
|
||||
if (!_stack) {
|
||||
_stack = get_stack();
|
||||
}
|
||||
if (_stack) {
|
||||
return _stack->get_ip_address();
|
||||
}
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::set_stack_type(nsapi_ip_stack_t stack_type)
|
||||
{
|
||||
if (get_modem_stack_type(stack_type)) {
|
||||
_ip_stack_type_requested = stack_type;
|
||||
return NSAPI_ERROR_OK;
|
||||
} else {
|
||||
return NSAPI_ERROR_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
nsapi_ip_stack_t AT_CellularNetwork::get_stack_type()
|
||||
{
|
||||
return _ip_stack_type;
|
||||
}
|
||||
|
||||
bool AT_CellularNetwork::get_modem_stack_type(nsapi_ip_stack_t requested_stack)
|
||||
{
|
||||
if (requested_stack == _ip_stack_type) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::set_access_technology_impl(RadioAccessTechnology opsAct)
|
||||
{
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
|
@ -1006,10 +427,11 @@ nsapi_error_t AT_CellularNetwork::scan_plmn(operList_t &operators, int &opsCount
|
|||
nsapi_error_t AT_CellularNetwork::set_ciot_optimization_config(Supported_UE_Opt supported_opt,
|
||||
Preferred_UE_Opt preferred_opt)
|
||||
{
|
||||
|
||||
_at.lock();
|
||||
|
||||
_at.cmd_start("AT+CCIOTOPT=");
|
||||
_at.write_int(_cid);
|
||||
_at.write_int(0); // disable urc
|
||||
_at.write_int(supported_opt);
|
||||
_at.write_int(preferred_opt);
|
||||
_at.cmd_stop_read_resp();
|
||||
|
@ -1037,138 +459,6 @@ nsapi_error_t AT_CellularNetwork::get_ciot_optimization_config(Supported_UE_Opt
|
|||
return _at.unlock_return_error();
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::get_rate_control(
|
||||
CellularNetwork::RateControlExceptionReports &reports,
|
||||
CellularNetwork::RateControlUplinkTimeUnit &timeUnit, int &uplinkRate)
|
||||
{
|
||||
|
||||
_at.lock();
|
||||
|
||||
_at.cmd_start("AT+CGAPNRC=");
|
||||
_at.write_int(_cid);
|
||||
_at.cmd_stop();
|
||||
|
||||
_at.resp_start("+CGAPNRC:");
|
||||
_at.read_int();
|
||||
if (_at.get_last_error() == NSAPI_ERROR_OK) {
|
||||
bool comma_found = true;
|
||||
int next_element = _at.read_int();
|
||||
if (next_element >= 0) {
|
||||
reports = (RateControlExceptionReports)next_element;
|
||||
tr_debug("reports %d", reports);
|
||||
next_element = _at.read_int();
|
||||
} else {
|
||||
comma_found = false;
|
||||
}
|
||||
|
||||
if (comma_found && next_element >= 0) {
|
||||
timeUnit = (RateControlUplinkTimeUnit)next_element;
|
||||
tr_debug("time %d", timeUnit);
|
||||
next_element = _at.read_int();
|
||||
} else {
|
||||
comma_found = false;
|
||||
}
|
||||
|
||||
if (comma_found && next_element >= 0) {
|
||||
uplinkRate = next_element;
|
||||
tr_debug("rate %d", uplinkRate);
|
||||
}
|
||||
}
|
||||
_at.resp_stop();
|
||||
|
||||
return _at.unlock_return_error();
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::get_pdpcontext_params(pdpContextList_t ¶ms_list)
|
||||
{
|
||||
const int ipv6_subnet_size = 128;
|
||||
const int max_ipv6_size = 64;
|
||||
char *ipv6_and_subnetmask = (char *)malloc(ipv6_subnet_size);
|
||||
if (!ipv6_and_subnetmask) {
|
||||
return NSAPI_ERROR_NO_MEMORY;
|
||||
}
|
||||
|
||||
char *temp = (char *)malloc(max_ipv6_size);
|
||||
if (!temp) {
|
||||
free(ipv6_and_subnetmask);
|
||||
return NSAPI_ERROR_NO_MEMORY;
|
||||
}
|
||||
|
||||
_at.lock();
|
||||
|
||||
_at.cmd_start("AT+CGCONTRDP=");
|
||||
_at.write_int(_cid);
|
||||
_at.cmd_stop();
|
||||
|
||||
_at.resp_start("+CGCONTRDP:");
|
||||
pdpcontext_params_t *params = NULL;
|
||||
while (_at.info_resp()) { // response can be zero or many +CGDCONT lines
|
||||
params = params_list.add_new();
|
||||
if (!params) {
|
||||
tr_warn("Could not allocate new pdpcontext_params_t");
|
||||
_at.resp_stop();
|
||||
_at.unlock();
|
||||
params_list.delete_all();
|
||||
free(temp);
|
||||
free(ipv6_and_subnetmask);
|
||||
return NSAPI_ERROR_NO_MEMORY;
|
||||
}
|
||||
|
||||
params->cid = _at.read_int();
|
||||
params->bearer_id = _at.read_int();
|
||||
_at.read_string(params->apn, sizeof(params->apn));
|
||||
|
||||
// rest are optional params
|
||||
ipv6_and_subnetmask[0] = '\0';
|
||||
temp[0] = '\0';
|
||||
_at.read_string(ipv6_and_subnetmask, ipv6_subnet_size);
|
||||
separate_ip_addresses(ipv6_and_subnetmask, params->local_addr, sizeof(params->local_addr), params->local_subnet_mask, sizeof(params->local_subnet_mask));
|
||||
ipv6_and_subnetmask[0] = '\0';
|
||||
|
||||
_at.read_string(ipv6_and_subnetmask, ipv6_subnet_size);
|
||||
separate_ip_addresses(ipv6_and_subnetmask, params->gateway_addr, sizeof(params->gateway_addr), temp, max_ipv6_size);
|
||||
prefer_ipv6(params->gateway_addr, sizeof(params->gateway_addr), temp, max_ipv6_size);
|
||||
ipv6_and_subnetmask[0] = '\0';
|
||||
temp[0] = '\0';
|
||||
|
||||
_at.read_string(ipv6_and_subnetmask, ipv6_subnet_size);
|
||||
separate_ip_addresses(ipv6_and_subnetmask, params->dns_primary_addr, sizeof(params->dns_primary_addr), temp, max_ipv6_size);
|
||||
prefer_ipv6(params->dns_primary_addr, sizeof(params->dns_primary_addr), temp, max_ipv6_size);
|
||||
ipv6_and_subnetmask[0] = '\0';
|
||||
temp[0] = '\0';
|
||||
|
||||
_at.read_string(ipv6_and_subnetmask, ipv6_subnet_size);
|
||||
separate_ip_addresses(ipv6_and_subnetmask, params->dns_secondary_addr, sizeof(params->dns_secondary_addr), temp, max_ipv6_size);
|
||||
prefer_ipv6(params->dns_secondary_addr, sizeof(params->dns_secondary_addr), temp, max_ipv6_size);
|
||||
ipv6_and_subnetmask[0] = '\0';
|
||||
temp[0] = '\0';
|
||||
|
||||
_at.read_string(ipv6_and_subnetmask, ipv6_subnet_size);
|
||||
separate_ip_addresses(ipv6_and_subnetmask, params->p_cscf_prim_addr, sizeof(params->p_cscf_prim_addr), temp, max_ipv6_size);
|
||||
prefer_ipv6(params->p_cscf_prim_addr, sizeof(params->p_cscf_prim_addr), temp, max_ipv6_size);
|
||||
ipv6_and_subnetmask[0] = '\0';
|
||||
temp[0] = '\0';
|
||||
|
||||
_at.read_string(ipv6_and_subnetmask, ipv6_subnet_size);
|
||||
separate_ip_addresses(ipv6_and_subnetmask, params->p_cscf_sec_addr, sizeof(params->p_cscf_sec_addr), temp, max_ipv6_size);
|
||||
prefer_ipv6(params->p_cscf_sec_addr, sizeof(params->p_cscf_sec_addr), temp, max_ipv6_size);
|
||||
|
||||
params->im_signalling_flag = _at.read_int();
|
||||
params->lipa_indication = _at.read_int();
|
||||
params->ipv4_mtu = _at.read_int();
|
||||
params->wlan_offload = _at.read_int();
|
||||
params->local_addr_ind = _at.read_int();
|
||||
params->non_ip_mtu = _at.read_int();
|
||||
params->serving_plmn_rate_control_value = _at.read_int();
|
||||
}
|
||||
_at.resp_stop();
|
||||
|
||||
free(temp);
|
||||
free(ipv6_and_subnetmask);
|
||||
|
||||
return _at.unlock_return_error();
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::get_extended_signal_quality(int &rxlev, int &ber, int &rscp, int &ecno, int &rsrq, int &rsrp)
|
||||
{
|
||||
_at.lock();
|
||||
|
@ -1276,6 +566,29 @@ nsapi_error_t AT_CellularNetwork::get_operator_names(operator_names_list &op_nam
|
|||
return _at.unlock_return_error();
|
||||
}
|
||||
|
||||
bool AT_CellularNetwork::is_active_context()
|
||||
{
|
||||
_at.lock();
|
||||
|
||||
bool active_found = false;
|
||||
// read active contexts
|
||||
_at.cmd_start("AT+CGACT?");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start("+CGACT:");
|
||||
while (_at.info_resp()) {
|
||||
(void)_at.read_int(); // discard context id
|
||||
if (_at.read_int() == 1) { // check state
|
||||
tr_debug("Found active context");
|
||||
active_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
_at.resp_stop();
|
||||
_at.unlock();
|
||||
|
||||
return active_found;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::get_registration_params(registration_params_t ®_params)
|
||||
{
|
||||
reg_params = _reg_params;
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
|
||||
#include "CellularNetwork.h"
|
||||
#include "AT_CellularBase.h"
|
||||
#include "NetworkStack.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
|
@ -33,7 +32,7 @@ namespace mbed {
|
|||
/**
|
||||
* Class AT_CellularNetwork
|
||||
*
|
||||
* Class for connecting to a network and getting information from it.
|
||||
* Class for attaching to a network and getting information from it.
|
||||
*/
|
||||
class AT_CellularNetwork : public CellularNetwork, public AT_CellularBase {
|
||||
|
||||
|
@ -44,52 +43,22 @@ public:
|
|||
// declare friend so it can access stack
|
||||
friend class AT_CellularDevice;
|
||||
|
||||
public: // NetworkInterface
|
||||
|
||||
virtual nsapi_error_t set_credentials(const char *apn,
|
||||
const char *username = 0, const char *password = 0);
|
||||
|
||||
virtual nsapi_error_t set_credentials(const char *apn, AuthenticationType type,
|
||||
const char *username = 0, const char *password = 0);
|
||||
|
||||
virtual nsapi_error_t connect(const char *apn,
|
||||
const char *username = 0, const char *password = 0);
|
||||
|
||||
virtual nsapi_error_t connect();
|
||||
|
||||
virtual nsapi_error_t disconnect();
|
||||
|
||||
protected:
|
||||
virtual NetworkStack *get_stack();
|
||||
|
||||
public: // CellularNetwork
|
||||
virtual nsapi_error_t init();
|
||||
|
||||
virtual nsapi_error_t activate_context();
|
||||
|
||||
virtual nsapi_error_t set_registration(const char *plmn = 0);
|
||||
|
||||
virtual nsapi_error_t get_network_registering_mode(NWRegisteringMode &mode);
|
||||
|
||||
virtual nsapi_error_t set_attach(int timeout = 10 * 1000);
|
||||
virtual nsapi_error_t set_attach();
|
||||
|
||||
virtual nsapi_error_t get_attach(AttachStatus &status);
|
||||
|
||||
virtual nsapi_error_t detach();
|
||||
|
||||
virtual nsapi_error_t get_rate_control(CellularNetwork::RateControlExceptionReports &reports,
|
||||
CellularNetwork::RateControlUplinkTimeUnit &time_unit, int &uplink_rate);
|
||||
|
||||
virtual nsapi_error_t get_apn_backoff_timer(int &backoff_timer);
|
||||
|
||||
virtual void attach(Callback<void(nsapi_event_t, intptr_t)> status_cb);
|
||||
|
||||
virtual nsapi_connection_status_t get_connection_status() const;
|
||||
|
||||
virtual nsapi_error_t set_blocking(bool blocking);
|
||||
|
||||
virtual const char *get_ip_address();
|
||||
|
||||
virtual nsapi_error_t set_access_technology(RadioAccessTechnology rat);
|
||||
|
||||
virtual nsapi_error_t scan_plmn(operList_t &operators, int &ops_count);
|
||||
|
@ -100,12 +69,6 @@ public: // CellularNetwork
|
|||
virtual nsapi_error_t get_ciot_optimization_config(Supported_UE_Opt &supported_opt,
|
||||
Preferred_UE_Opt &preferred_opt);
|
||||
|
||||
virtual nsapi_error_t set_stack_type(nsapi_ip_stack_t stack_type);
|
||||
|
||||
virtual nsapi_ip_stack_t get_stack_type();
|
||||
|
||||
virtual nsapi_error_t get_pdpcontext_params(pdpContextList_t ¶ms_list);
|
||||
|
||||
virtual nsapi_error_t get_extended_signal_quality(int &rxlev, int &ber, int &rscp, int &ecno, int &rsrq, int &rsrp);
|
||||
|
||||
virtual nsapi_error_t get_signal_quality(int &rssi, int &ber);
|
||||
|
@ -118,17 +81,13 @@ public: // CellularNetwork
|
|||
|
||||
virtual nsapi_error_t get_operator_names(operator_names_list &op_names);
|
||||
|
||||
virtual bool is_active_context();
|
||||
|
||||
virtual nsapi_error_t get_registration_params(registration_params_t ®_params);
|
||||
|
||||
virtual nsapi_error_t get_registration_params(RegistrationType type, registration_params_t ®_params);
|
||||
protected:
|
||||
|
||||
/** Check if modem supports the given stack type.
|
||||
*
|
||||
* @return true if supported
|
||||
*/
|
||||
virtual bool get_modem_stack_type(nsapi_ip_stack_t requested_stack);
|
||||
|
||||
/** Check if modem supports given registration type.
|
||||
*
|
||||
* @param reg_type enum RegistrationType
|
||||
|
@ -149,13 +108,6 @@ protected:
|
|||
*/
|
||||
virtual nsapi_error_t set_access_technology_impl(RadioAccessTechnology op_rat);
|
||||
|
||||
/** APN user authentication
|
||||
*
|
||||
* @return NSAPI_ERROR_OK on success
|
||||
* NSAPI_ERROR_UNSUPPORTED on authentication not supported by cellular device
|
||||
* NSAPI_ERROR_AUTH_FAILURE on authentication to network failed
|
||||
*/
|
||||
virtual nsapi_error_t do_user_authentication();
|
||||
private:
|
||||
// "NO CARRIER" urc
|
||||
void urc_no_carrier();
|
||||
|
@ -164,19 +116,6 @@ private:
|
|||
void urc_cgreg();
|
||||
void urc_cgev();
|
||||
|
||||
nsapi_ip_stack_t string_to_stack_type(const char *pdp_type);
|
||||
|
||||
void free_credentials();
|
||||
|
||||
nsapi_error_t open_data_channel();
|
||||
bool get_context();
|
||||
bool set_new_context(int cid);
|
||||
|
||||
nsapi_error_t delete_current_context();
|
||||
|
||||
// calls network callback only if status was changed, updates local connection status
|
||||
void call_network_cb(nsapi_connection_status_t status);
|
||||
|
||||
void read_reg_params_and_compare(RegistrationType type);
|
||||
void read_reg_params(registration_params_t ®_params);
|
||||
|
||||
|
@ -185,27 +124,15 @@ private:
|
|||
// Returns periodic tau(Table 10.5.163a/3GPP TS 24.008: GPRS Timer 3 information element) in seconds
|
||||
int calculate_periodic_tau(const char *periodic_tau_string, int periodic_tau_length);
|
||||
|
||||
#if NSAPI_PPP_AVAILABLE
|
||||
void ppp_status_cb(nsapi_event_t, intptr_t);
|
||||
#endif
|
||||
// calls network callback only if status was changed, updates local connection status
|
||||
void call_network_cb(nsapi_connection_status_t status);
|
||||
|
||||
protected:
|
||||
NetworkStack *_stack;
|
||||
char *_apn;
|
||||
char *_uname;
|
||||
char *_pwd;
|
||||
nsapi_ip_stack_t _ip_stack_type_requested;
|
||||
nsapi_ip_stack_t _ip_stack_type;
|
||||
int _cid;
|
||||
|
||||
Callback<void(nsapi_event_t, intptr_t)> _connection_status_cb;
|
||||
RadioAccessTechnology _op_act;
|
||||
AuthenticationType _authentication_type;
|
||||
nsapi_connection_status_t _connect_status;
|
||||
bool _new_context_set;
|
||||
bool _is_context_active;
|
||||
|
||||
registration_params_t _reg_params;
|
||||
|
||||
mbed::Callback<void()> _urc_funcs[C_MAX];
|
||||
};
|
||||
|
||||
|
|
|
@ -24,10 +24,12 @@
|
|||
struct cell_callback_data_t {
|
||||
nsapi_error_t error; /* possible error code */
|
||||
int status_data; /* cellular_event_status related enum or other info in int format. Check cellular_event_status comments.*/
|
||||
bool final_try; /* This flag is true if state machine is used and this was the last try. State machine does goes to idle. */
|
||||
|
||||
cell_callback_data_t() {
|
||||
error = NSAPI_ERROR_OK;
|
||||
status_data = -1;
|
||||
final_try = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* 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 "CellularContext.h"
|
||||
|
||||
namespace mbed {
|
||||
#ifdef CELLULAR_DEVICE
|
||||
MBED_WEAK NetworkInterface *CellularContext::get_default_instance()
|
||||
{
|
||||
// Uses default APN, uname, password from mbed_app.json
|
||||
static CellularDevice *dev = CellularDevice::get_default_instance();
|
||||
return dev->create_context();
|
||||
}
|
||||
#else
|
||||
MBED_WEAK NetworkInterface *CellularContext::get_default_instance()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif // CELLULAR_DEVICE
|
||||
|
||||
} // namespace mbed
|
|
@ -16,6 +16,8 @@
|
|||
*/
|
||||
|
||||
#include "CellularDevice.h"
|
||||
#include "CellularContext.h"
|
||||
#include "CellularSIM.h"
|
||||
#include "CellularUtil.h"
|
||||
#include "CellularLog.h"
|
||||
#include "CellularTargets.h"
|
||||
|
@ -31,7 +33,7 @@ namespace mbed {
|
|||
#ifdef CELLULAR_DEVICE
|
||||
MBED_WEAK CellularDevice *CellularDevice::get_default_instance()
|
||||
{
|
||||
static events::EventQueue event_queue(4 * EVENTS_EVENT_SIZE);
|
||||
static events::EventQueue event_queue(5 * EVENTS_EVENT_SIZE);
|
||||
static CELLULAR_DEVICE device(event_queue);
|
||||
return &device;
|
||||
}
|
||||
|
@ -42,10 +44,11 @@ MBED_WEAK CellularDevice *CellularDevice::get_default_instance()
|
|||
}
|
||||
#endif // CELLULAR_DEVICE
|
||||
|
||||
CellularDevice::CellularDevice() : _error(NSAPI_ERROR_OK), _network_ref_count(0), _sms_ref_count(0),
|
||||
_power_ref_count(0), _sim_ref_count(0), _info_ref_count(0), _is_connected(false),
|
||||
_state_machine(0), _fh(0)
|
||||
CellularDevice::CellularDevice() : _network_ref_count(0), _sms_ref_count(0),_power_ref_count(0), _sim_ref_count(0),
|
||||
_info_ref_count(0), _fh(0), _error(0), _state_machine(0), _nw(0)
|
||||
{
|
||||
set_sim_pin(MBED_CONF_NSAPI_DEFAULT_CELLULAR_SIM_PIN);
|
||||
set_plmn(MBED_CONF_NSAPI_DEFAULT_CELLULAR_PLMN);
|
||||
}
|
||||
|
||||
CellularDevice::~CellularDevice()
|
||||
|
@ -59,138 +62,136 @@ void CellularDevice::stop()
|
|||
_state_machine->stop();
|
||||
}
|
||||
|
||||
bool CellularDevice::is_connected() const
|
||||
{
|
||||
return _is_connected;
|
||||
}
|
||||
|
||||
events::EventQueue *CellularDevice::get_queue() const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nsapi_error_t CellularDevice::set_credentials(const char *apn, const char *uname, const char *pwd)
|
||||
CellularContext *CellularDevice::get_context_list() const {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FileHandle &CellularDevice::get_filehandle() const
|
||||
{
|
||||
MBED_ASSERT(_state_machine);
|
||||
return _state_machine->set_credentials(apn, uname, pwd);
|
||||
return *_fh;
|
||||
}
|
||||
|
||||
void CellularDevice::set_sim_pin(const char *sim_pin)
|
||||
{
|
||||
MBED_ASSERT(_state_machine);
|
||||
_state_machine->set_sim_pin(sim_pin);
|
||||
}
|
||||
|
||||
nsapi_error_t CellularDevice::init_stm(FileHandle *fh)
|
||||
{
|
||||
MBED_ASSERT(!_state_machine);
|
||||
|
||||
if (fh == NULL) {
|
||||
return NSAPI_ERROR_PARAMETER;
|
||||
if (sim_pin) {
|
||||
strncpy(_sim_pin, sim_pin, sizeof(_sim_pin));
|
||||
_sim_pin[sizeof(_sim_pin) - 1] = '\0';
|
||||
} else {
|
||||
memset(_sim_pin, 0, sizeof(_sim_pin));
|
||||
}
|
||||
_fh = fh;
|
||||
|
||||
_state_machine = new CellularStateMachine(*this, *get_queue(), open_power(_fh));
|
||||
_state_machine->attach(callback(this, &CellularDevice::network_callback));
|
||||
_state_machine->set_sim(open_sim(_fh));
|
||||
CellularNetwork *nw = open_network(_fh);
|
||||
_state_machine->set_network(nw);
|
||||
|
||||
nsapi_error_t err = nw->init();
|
||||
if (err != NSAPI_ERROR_OK) {
|
||||
delete _state_machine;
|
||||
_state_machine = NULL;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
nsapi_error_t CellularDevice::start_dispatch() {
|
||||
MBED_ASSERT(_state_machine);
|
||||
return _state_machine->start_dispatch();
|
||||
}
|
||||
|
||||
nsapi_error_t CellularDevice::set_device_ready()
|
||||
{
|
||||
return _state_machine->run_to_state(CellularStateMachine::STATE_DEVICE_READY);
|
||||
}
|
||||
|
||||
nsapi_error_t CellularDevice::set_sim_ready()
|
||||
{
|
||||
return _state_machine->run_to_state(CellularStateMachine::STATE_SIM_PIN);
|
||||
}
|
||||
|
||||
nsapi_error_t CellularDevice::register_to_network()
|
||||
{
|
||||
return _state_machine->run_to_state(CellularStateMachine::STATE_REGISTERING_NETWORK);
|
||||
}
|
||||
|
||||
nsapi_error_t CellularDevice::attach_to_network()
|
||||
{
|
||||
return _state_machine->run_to_state(CellularStateMachine::STATE_ATTACHING_NETWORK);
|
||||
}
|
||||
|
||||
nsapi_error_t CellularDevice::activate_context()
|
||||
{
|
||||
return _state_machine->run_to_state(CellularStateMachine::STATE_ACTIVATING_PDP_CONTEXT);
|
||||
}
|
||||
|
||||
nsapi_error_t CellularDevice::connect(const char *sim_pin, const char *apn,
|
||||
const char *uname, const char *pwd)
|
||||
{
|
||||
set_sim_pin(sim_pin);
|
||||
set_credentials(apn, uname, pwd);
|
||||
return connect();
|
||||
}
|
||||
|
||||
nsapi_error_t CellularDevice::connect()
|
||||
{
|
||||
return _state_machine->run_to_state(CellularStateMachine::STATE_CONNECTED);
|
||||
}
|
||||
|
||||
nsapi_error_t CellularDevice::disconnect()
|
||||
{
|
||||
MBED_ASSERT(_state_machine);
|
||||
return _state_machine->disconnect();
|
||||
}
|
||||
|
||||
void CellularDevice::set_plmn(const char* plmn)
|
||||
{
|
||||
MBED_ASSERT(_state_machine);
|
||||
_state_machine->set_plmn(plmn);
|
||||
if (plmn) {
|
||||
strncpy(_plmn, plmn, sizeof(_plmn));
|
||||
_plmn[sizeof(_plmn) - 1] = '\0';
|
||||
} else {
|
||||
memset(_plmn, 0, sizeof(_plmn));
|
||||
}
|
||||
}
|
||||
|
||||
void CellularDevice::set_blocking(bool blocking)
|
||||
{
|
||||
MBED_ASSERT(_state_machine);
|
||||
_state_machine->set_blocking(blocking);
|
||||
nsapi_error_t CellularDevice::start_dispatch() {
|
||||
_mutex.lock();
|
||||
create_state_machine();
|
||||
nsapi_error_t err = _state_machine->start_dispatch();
|
||||
_mutex.unlock();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void CellularDevice::attach(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb)
|
||||
nsapi_error_t CellularDevice::set_device_ready()
|
||||
{
|
||||
_nw_status_cb = status_cb;
|
||||
return start_state_machine(CellularStateMachine::STATE_DEVICE_READY);
|
||||
}
|
||||
|
||||
void CellularDevice::network_callback(nsapi_event_t ev, intptr_t ptr)
|
||||
nsapi_error_t CellularDevice::set_sim_ready()
|
||||
{
|
||||
if (ev == NSAPI_EVENT_CONNECTION_STATUS_CHANGE) {
|
||||
if (ptr == NSAPI_STATUS_GLOBAL_UP) {
|
||||
_is_connected = true;
|
||||
} else {
|
||||
_is_connected = false;
|
||||
}
|
||||
return start_state_machine(CellularStateMachine::STATE_SIM_PIN);
|
||||
}
|
||||
|
||||
nsapi_error_t CellularDevice::register_to_network()
|
||||
{
|
||||
return start_state_machine(CellularStateMachine::STATE_REGISTERING_NETWORK);
|
||||
}
|
||||
|
||||
nsapi_error_t CellularDevice::attach_to_network()
|
||||
{
|
||||
return start_state_machine(CellularStateMachine::STATE_ATTACHING_NETWORK);
|
||||
}
|
||||
|
||||
void CellularDevice::create_state_machine()
|
||||
{
|
||||
if (!_state_machine) {
|
||||
_state_machine = new CellularStateMachine(*this, *get_queue());
|
||||
_state_machine->set_cellular_callback(callback(this, &CellularDevice::cellular_callback));
|
||||
}
|
||||
}
|
||||
|
||||
nsapi_error_t CellularDevice::start_state_machine(CellularStateMachine::CellularState target_state)
|
||||
{
|
||||
_mutex.lock();
|
||||
create_state_machine();
|
||||
|
||||
CellularStateMachine::CellularState current_state, targeted_state;
|
||||
|
||||
bool is_running = _state_machine->get_current_status(current_state, targeted_state);
|
||||
|
||||
if (current_state >= target_state) { // can stm be in this state but failed?
|
||||
_mutex.unlock();
|
||||
return NSAPI_ERROR_ALREADY;
|
||||
} else if (is_running && targeted_state >= target_state) {
|
||||
_mutex.unlock();
|
||||
return NSAPI_ERROR_IN_PROGRESS;
|
||||
}
|
||||
|
||||
nsapi_error_t err = _state_machine->run_to_state(target_state);
|
||||
_mutex.unlock();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void CellularDevice::cellular_callback(nsapi_event_t ev, intptr_t ptr)
|
||||
{
|
||||
if (ev >= NSAPI_EVENT_CELLULAR_STATUS_BASE && ev <= NSAPI_EVENT_CELLULAR_STATUS_END) {
|
||||
tr_debug("Device: network_callback called with event: %d, err: %d, data: %d", ev, ((cell_callback_data_t*)ptr)->error, ((cell_callback_data_t*)ptr)->status_data);
|
||||
cell_callback_data_t* ptr_data = (cell_callback_data_t*)ptr;
|
||||
tr_debug("Device: network_callback called with event: %d, err: %d, data: %d", ev, ptr_data->error, ptr_data->status_data);
|
||||
cellular_connection_status_t cell_ev = (cellular_connection_status_t)ev;
|
||||
if (cell_ev == CellularRegistrationStatusChanged && _state_machine) {
|
||||
// broadcast only network registration changes to state machine
|
||||
_state_machine->cellular_event_changed(ev, ptr);
|
||||
}
|
||||
|
||||
if (cell_ev == CellularDeviceReady && ptr_data->error == NSAPI_ERROR_OK) {
|
||||
// Here we can create mux and give new filehandles as mux reserves the one what was in use.
|
||||
// if mux we would need to set new filehandle:_state_machine->set_filehandle( get fh from mux);
|
||||
_nw = open_network(_fh);
|
||||
// Attach to network so we can get update status from the network
|
||||
_nw->attach(callback(this, &CellularDevice::cellular_callback));
|
||||
} else if (cell_ev == CellularSIMStatusChanged && ptr_data->error == NSAPI_ERROR_OK &&
|
||||
ptr_data->status_data == CellularSIM::SimStatePinNeeded) {
|
||||
if (strlen(_sim_pin)) {
|
||||
_state_machine->set_sim_pin(_sim_pin);
|
||||
}
|
||||
if (strlen(_plmn)) {
|
||||
_state_machine->set_plmn(_plmn);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tr_debug("Device: network_callback called with event: %d, ptr: %d", ev, ptr);
|
||||
}
|
||||
// forward network callback to application is it has registered with attach
|
||||
if (_nw_status_cb) {
|
||||
_nw_status_cb(ev, ptr);
|
||||
|
||||
// broadcast network and cellular changes to state machine and CellularContext.
|
||||
CellularContext *curr = get_context_list();
|
||||
while (curr) {
|
||||
curr->cellular_callback(ev, ptr);
|
||||
curr = curr->_next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespae mbed
|
||||
} // namespace mbed
|
||||
|
|
|
@ -17,10 +17,9 @@
|
|||
|
||||
#include "CellularStateMachine.h"
|
||||
#include "CellularDevice.h"
|
||||
#include "CellularLog.h"
|
||||
#include "CellularUtil.h"
|
||||
#include "CellularPower.h"
|
||||
#include "CellularSIM.h"
|
||||
#include "CellularLog.h"
|
||||
#include "Thread.h"
|
||||
#include "UARTSerial.h"
|
||||
|
||||
|
@ -42,14 +41,13 @@
|
|||
|
||||
namespace mbed {
|
||||
|
||||
CellularStateMachine::CellularStateMachine(CellularDevice &device, events::EventQueue &queue, CellularPower *power) :
|
||||
CellularStateMachine::CellularStateMachine(CellularDevice &device, events::EventQueue &queue) :
|
||||
_cellularDevice(device), _state(STATE_INIT), _next_state(_state), _target_state(_state),
|
||||
_event_status_cb(0), _network(0), _power(power), _sim(0), _queue(queue), _queue_thread(0), _retry_count(0),
|
||||
_event_timeout(-1), _event_id(0), _plmn(0), _command_success(false), _plmn_network_found(false), _cb_data(),
|
||||
_current_event(NSAPI_EVENT_CONNECTION_STATUS_CHANGE), _automatic_reconnect(true), _blocking(true),
|
||||
_stm_semaphore(0)
|
||||
_event_status_cb(0), _network(0), _power(0), _sim(0), _queue(queue), _queue_thread(0), _sim_pin(0),
|
||||
_retry_count(0), _event_timeout(-1), _event_id(-1), _plmn(0), _command_success(false),
|
||||
_plmn_network_found(false), _is_retry(false), _cb_data(), _current_event(NSAPI_EVENT_CONNECTION_STATUS_CHANGE),
|
||||
_active_context(false)
|
||||
{
|
||||
memset(_sim_pin, 0, sizeof(_sim_pin));
|
||||
#if MBED_CONF_CELLULAR_RANDOM_MAX_START_DELAY == 0
|
||||
_start_time = 0;
|
||||
#else
|
||||
|
@ -92,6 +90,9 @@ void CellularStateMachine::stop()
|
|||
_target_state = _state;
|
||||
_cb_data.error = NSAPI_ERROR_OK;
|
||||
_cb_data.status_data = -1;
|
||||
_cb_data.final_try = false;
|
||||
_event_id = -1;
|
||||
_is_retry = false;
|
||||
|
||||
if (_power) {
|
||||
_cellularDevice.close_power();
|
||||
|
@ -109,52 +110,11 @@ void CellularStateMachine::stop()
|
|||
}
|
||||
}
|
||||
|
||||
void CellularStateMachine::set_blocking(bool blocking)
|
||||
{
|
||||
_blocking = blocking;
|
||||
}
|
||||
|
||||
void CellularStateMachine::set_automatic_reconnect(bool do_reconnect)
|
||||
{
|
||||
_automatic_reconnect = do_reconnect;
|
||||
}
|
||||
|
||||
events::EventQueue *CellularStateMachine::get_queue() const
|
||||
{
|
||||
return &_queue;
|
||||
}
|
||||
|
||||
nsapi_error_t CellularStateMachine::set_credentials(const char *apn, const char *uname, const char *pwd)
|
||||
{
|
||||
return _network->set_credentials(apn, uname, pwd);
|
||||
}
|
||||
|
||||
void CellularStateMachine::set_sim(CellularSIM* sim)
|
||||
{
|
||||
if (_sim) {
|
||||
// we own this so we'll close it before accepting new one
|
||||
_cellularDevice.close_sim();
|
||||
}
|
||||
_sim = sim;
|
||||
}
|
||||
|
||||
void CellularStateMachine::set_network(CellularNetwork* nw)
|
||||
{
|
||||
if (_network) {
|
||||
_cellularDevice.close_network();
|
||||
}
|
||||
_network = nw;
|
||||
_network->attach(callback(this, &CellularStateMachine::network_callback));
|
||||
}
|
||||
|
||||
void CellularStateMachine::set_power(CellularPower* pwr)
|
||||
{
|
||||
if (_power) {
|
||||
_cellularDevice.close_power();
|
||||
}
|
||||
_power = pwr;
|
||||
}
|
||||
|
||||
bool CellularStateMachine::power_on()
|
||||
{
|
||||
_cb_data.error = _power->on();
|
||||
|
@ -171,8 +131,7 @@ bool CellularStateMachine::power_on()
|
|||
|
||||
void CellularStateMachine::set_sim_pin(const char *sim_pin)
|
||||
{
|
||||
strncpy(_sim_pin, sim_pin, sizeof(_sim_pin));
|
||||
_sim_pin[sizeof(_sim_pin) - 1] = '\0';
|
||||
_sim_pin = sim_pin;
|
||||
}
|
||||
|
||||
void CellularStateMachine::set_plmn(const char *plmn)
|
||||
|
@ -182,16 +141,17 @@ void CellularStateMachine::set_plmn(const char *plmn)
|
|||
|
||||
bool CellularStateMachine::open_sim()
|
||||
{
|
||||
if (!_sim) {
|
||||
// can only fail with allocation with new and then it's critical error
|
||||
_sim = _cellularDevice.open_sim();
|
||||
}
|
||||
|
||||
CellularSIM::SimState state = CellularSIM::SimStateUnknown;
|
||||
// wait until SIM is readable
|
||||
// here you could add wait(secs) if you know start delay of your SIM
|
||||
_cb_data.error = _sim->get_sim_state(state);
|
||||
if (_cb_data.error != NSAPI_ERROR_OK) {
|
||||
tr_info("Waiting for SIM (err while reading)...");
|
||||
if (_event_status_cb) {
|
||||
_cb_data.status_data = state;
|
||||
_event_status_cb((nsapi_event_t)CellularSIMStatusChanged, (intptr_t )&_cb_data);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -233,7 +193,7 @@ bool CellularStateMachine::is_registered()
|
|||
}
|
||||
}
|
||||
|
||||
return is_registered;
|
||||
return is_registered || _active_context;
|
||||
}
|
||||
|
||||
bool CellularStateMachine::get_network_registration(CellularNetwork::RegistrationType type,
|
||||
|
@ -241,28 +201,31 @@ bool CellularStateMachine::get_network_registration(CellularNetwork::Registratio
|
|||
{
|
||||
is_registered = false;
|
||||
bool is_roaming = false;
|
||||
_cb_data.error = _network->get_registration_status(type, status);
|
||||
CellularNetwork::registration_params_t reg_params;
|
||||
_cb_data.error = _network->get_registration_params(type, reg_params);
|
||||
|
||||
if (_cb_data.error != NSAPI_ERROR_OK) {
|
||||
if (_cb_data.error != NSAPI_ERROR_UNSUPPORTED) {
|
||||
tr_warn("Get network registration failed (type %d)!", type);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
status = reg_params._status;
|
||||
switch (status) {
|
||||
case CellularNetwork::RegisteredRoaming:
|
||||
is_roaming = true;
|
||||
is_roaming = true;// @suppress("No break at end of case")
|
||||
// fall-through
|
||||
case CellularNetwork::RegisteredHomeNetwork:
|
||||
is_registered = true;
|
||||
break;
|
||||
case CellularNetwork::RegisteredSMSOnlyRoaming:
|
||||
is_roaming = true;
|
||||
is_roaming = true;// @suppress("No break at end of case")
|
||||
// fall-through
|
||||
case CellularNetwork::RegisteredSMSOnlyHome:
|
||||
tr_warn("SMS only network registration!");
|
||||
break;
|
||||
case CellularNetwork::RegisteredCSFBNotPreferredRoaming:
|
||||
is_roaming = true;
|
||||
is_roaming = true; // @suppress("No break at end of case")
|
||||
// fall-through
|
||||
case CellularNetwork::RegisteredCSFBNotPreferredHome:
|
||||
tr_warn("Not preferred network registration!");
|
||||
|
@ -289,20 +252,19 @@ void CellularStateMachine::report_failure(const char *msg)
|
|||
{
|
||||
tr_error("Cellular stm failed with: %s", msg);
|
||||
|
||||
_event_id = -1;
|
||||
if (_event_status_cb) {
|
||||
_cb_data.final_try = true;
|
||||
_event_status_cb(_current_event, (intptr_t )&_cb_data);
|
||||
}
|
||||
|
||||
tr_error("Target state %s was not reached. Returning from state: %s", get_state_string(_target_state), get_state_string(_state));
|
||||
if (_blocking) {
|
||||
_stm_semaphore.release();
|
||||
}
|
||||
}
|
||||
|
||||
const char *CellularStateMachine::get_state_string(CellularState state) const
|
||||
{
|
||||
#if MBED_CONF_MBED_TRACE_ENABLE
|
||||
static const char *strings[STATE_MAX_FSM_STATE] = { "Init", "Power", "Device ready", "SIM pin", "Registering network", "Manual registering", "Attaching network", "Activating PDP Context", "Connecting network", "Connected", "Disconnecting"};
|
||||
static const char *strings[STATE_MAX_FSM_STATE] = { "Init", "Power", "Device ready", "SIM pin", "Registering network", "Manual registering", "Attaching network"};
|
||||
return strings[state];
|
||||
#else
|
||||
return NULL;
|
||||
|
@ -357,46 +319,6 @@ bool CellularStateMachine::is_registered_to_plmn()
|
|||
return false;
|
||||
}
|
||||
|
||||
void CellularStateMachine::continue_from_state(CellularState state)
|
||||
{
|
||||
tr_info("Continue state from %s to %s", get_state_string((CellularStateMachine::CellularState)_state),
|
||||
get_state_string((CellularStateMachine::CellularState)state));
|
||||
_state = state;
|
||||
enter_to_state(state);
|
||||
_event_id = _queue.call_in(0, callback(this, &CellularStateMachine::event));
|
||||
if (!_event_id) {
|
||||
_cb_data.error = NSAPI_ERROR_NO_MEMORY;
|
||||
report_failure("Failed to call queue.");
|
||||
stop();
|
||||
}
|
||||
}
|
||||
|
||||
nsapi_error_t CellularStateMachine::run_to_state(CellularStateMachine::CellularState state)
|
||||
{
|
||||
// update next state so that we don't continue from previous state if state machine was paused and then started again.
|
||||
_state = _next_state;
|
||||
_target_state = state;
|
||||
enter_to_state(_next_state);
|
||||
|
||||
_event_id = _queue.call_in(0, callback(this, &CellularStateMachine::event));
|
||||
|
||||
if (!_event_id) {
|
||||
stop();
|
||||
return NSAPI_ERROR_NO_MEMORY;
|
||||
}
|
||||
|
||||
if (_blocking) {
|
||||
// TODO, should we adjust semaphore wait time according to state we are trying to achieve?
|
||||
int ret_wait = _stm_semaphore.wait(10 * 60 * 1000); // cellular network searching may take several minutes
|
||||
if (ret_wait != 1) {
|
||||
tr_info("No cellular connection");
|
||||
return NSAPI_ERROR_NO_CONNECTION;
|
||||
}
|
||||
}
|
||||
|
||||
return _cb_data.error;
|
||||
}
|
||||
|
||||
void CellularStateMachine::enter_to_state(CellularState state)
|
||||
{
|
||||
_next_state = state;
|
||||
|
@ -404,6 +326,7 @@ void CellularStateMachine::enter_to_state(CellularState state)
|
|||
_command_success = false;
|
||||
_cb_data.error = NSAPI_ERROR_OK;
|
||||
_cb_data.status_data = -1;
|
||||
_cb_data.final_try = false;
|
||||
}
|
||||
|
||||
void CellularStateMachine::retry_state_or_fail()
|
||||
|
@ -411,6 +334,7 @@ void CellularStateMachine::retry_state_or_fail()
|
|||
if (++_retry_count < RETRY_ARRAY_SIZE) {
|
||||
tr_debug("Retry State %s, retry %d/%d", get_state_string(_state), _retry_count, RETRY_ARRAY_SIZE);
|
||||
_event_timeout = _retry_timeout_array[_retry_count];
|
||||
_is_retry = true;
|
||||
} else {
|
||||
report_failure(get_state_string(_state));
|
||||
return;
|
||||
|
@ -422,6 +346,9 @@ void CellularStateMachine::state_init()
|
|||
// we should check that if power is already on then we can jump to device ready state
|
||||
_cellularDevice.set_timeout(TIMEOUT_POWER_ON);
|
||||
tr_info("Cellular state init (timeout %d ms)", TIMEOUT_POWER_ON);
|
||||
if (!_power) {
|
||||
_power = _cellularDevice.open_power();
|
||||
}
|
||||
_cb_data.error = _power->is_device_ready();
|
||||
if (_cb_data.error != NSAPI_ERROR_OK) {
|
||||
_event_timeout = _start_time;
|
||||
|
@ -465,7 +392,7 @@ void CellularStateMachine::state_device_ready()
|
|||
enter_to_state(STATE_SIM_PIN);
|
||||
} else {
|
||||
if (_retry_count == 0) {
|
||||
(void)_power->set_device_ready_urc_cb(mbed::callback(this, &CellularStateMachine::ready_urc_cb));
|
||||
_power->set_device_ready_urc_cb(mbed::callback(this, &CellularStateMachine::ready_urc_cb));
|
||||
}
|
||||
retry_state_or_fail();
|
||||
}
|
||||
|
@ -476,6 +403,10 @@ void CellularStateMachine::state_sim_pin()
|
|||
_cellularDevice.set_timeout(TIMEOUT_SIM_PIN);
|
||||
tr_info("Sim state (timeout %d ms)", TIMEOUT_SIM_PIN);
|
||||
if (open_sim()) {
|
||||
if (!_network) {
|
||||
_network = _cellularDevice.open_network();
|
||||
}
|
||||
|
||||
bool success = false;
|
||||
for (int type = 0; type < CellularNetwork::C_MAX; type++) {
|
||||
_cb_data.error = _network->set_registration_urc((CellularNetwork::RegistrationType)type, true);
|
||||
|
@ -488,6 +419,9 @@ void CellularStateMachine::state_sim_pin()
|
|||
retry_state_or_fail();
|
||||
return;
|
||||
}
|
||||
|
||||
_active_context = false;
|
||||
_active_context = _network->is_active_context(); // check if context was already activated
|
||||
if (_plmn) {
|
||||
enter_to_state(STATE_MANUAL_REGISTERING_NETWORK);
|
||||
} else {
|
||||
|
@ -537,6 +471,7 @@ void CellularStateMachine::state_attaching()
|
|||
{
|
||||
_cellularDevice.set_timeout(TIMEOUT_CONNECT);
|
||||
_cb_data.error = _network->set_attach();
|
||||
tr_info("CellularStateMachine::state_attaching(): %d", _cb_data.error);
|
||||
if (_cb_data.error == NSAPI_ERROR_OK) {
|
||||
_cellularDevice.close_sim();
|
||||
_sim = NULL;
|
||||
|
@ -544,45 +479,86 @@ void CellularStateMachine::state_attaching()
|
|||
_cb_data.status_data = CellularNetwork::Attached;
|
||||
_event_status_cb(_current_event, (intptr_t )&_cb_data);
|
||||
}
|
||||
enter_to_state(STATE_ACTIVATING_PDP_CONTEXT);
|
||||
} else {
|
||||
retry_state_or_fail();
|
||||
}
|
||||
}
|
||||
|
||||
void CellularStateMachine::state_activating_pdp_context()
|
||||
void CellularStateMachine::continue_from_state(CellularState state)
|
||||
{
|
||||
_cellularDevice.set_timeout(TIMEOUT_CONNECT);
|
||||
tr_info("Activate PDP Context (timeout %d ms)", TIMEOUT_CONNECT);
|
||||
_cb_data.error = _network->activate_context();
|
||||
if (_cb_data.error == NSAPI_ERROR_OK) {
|
||||
if (_event_status_cb) {
|
||||
_event_status_cb(_current_event, (intptr_t )&_cb_data);
|
||||
_mutex.lock();
|
||||
tr_info("Continue state from %s to %s", get_state_string((CellularStateMachine::CellularState)_state),
|
||||
get_state_string((CellularStateMachine::CellularState)state));
|
||||
_state = state;
|
||||
enter_to_state(state);
|
||||
_event_id = _queue.call_in(0, this, &CellularStateMachine::event);
|
||||
if (!_event_id) {
|
||||
_event_id = -1;
|
||||
_cb_data.error = NSAPI_ERROR_NO_MEMORY;
|
||||
report_failure("Failed to call queue.");
|
||||
stop();
|
||||
}
|
||||
_mutex.unlock();
|
||||
}
|
||||
|
||||
nsapi_error_t CellularStateMachine::run_to_state(CellularStateMachine::CellularState state)
|
||||
{
|
||||
_mutex.lock();
|
||||
// call pre_event via queue so that it's in same thread and it's safe to decisions
|
||||
int id = _queue.call_in(0, this, &CellularStateMachine::pre_event, state);
|
||||
if (!id) {
|
||||
stop();
|
||||
_mutex.unlock();
|
||||
return NSAPI_ERROR_NO_MEMORY;
|
||||
}
|
||||
_mutex.unlock();
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
void CellularStateMachine::pre_event(CellularState state)
|
||||
{
|
||||
tr_debug("CellularStateMachine::pre_event, state: %s, _target_state: %s, _event_id: %d", get_state_string(state), get_state_string(_target_state), _event_id);
|
||||
if (_target_state < state) {
|
||||
// new wanted state will not be achieved with current _target_state so update it
|
||||
_target_state = state;
|
||||
} else {
|
||||
// wanted state is already / will be achieved, return without launching new event
|
||||
return;
|
||||
}
|
||||
// if _event_id is -1 it means that new event is not going to be launched so we must launch new event
|
||||
if (_event_id == -1) {
|
||||
if (!_cb_data.final_try) {
|
||||
// update next state so that we don't continue from previous state if state machine was paused and then started again.
|
||||
// but only if earlier try did not finish to failure, then we must continue from that state
|
||||
_state = _next_state;
|
||||
}
|
||||
enter_to_state(_next_state);
|
||||
_event_id = _queue.call_in(0, this, &CellularStateMachine::event);
|
||||
if (!_event_id) {
|
||||
_event_id = -1;
|
||||
report_failure("Failed to call queue.");
|
||||
stop();
|
||||
}
|
||||
enter_to_state(STATE_CONNECTING_NETWORK);
|
||||
} else {
|
||||
retry_state_or_fail();
|
||||
}
|
||||
}
|
||||
|
||||
void CellularStateMachine::state_connect_to_network()
|
||||
bool CellularStateMachine::get_current_status(CellularStateMachine::CellularState ¤t_state, CellularStateMachine::CellularState &target_state)
|
||||
{
|
||||
_cellularDevice.set_timeout(TIMEOUT_CONNECT);
|
||||
tr_info("Connect to cellular network (timeout %d ms)", TIMEOUT_CONNECT);
|
||||
_cb_data.error = _network->connect();
|
||||
if (_cb_data.error == NSAPI_ERROR_OK) {
|
||||
_cellularDevice.set_timeout(TIMEOUT_NETWORK);
|
||||
tr_debug("Connected to cellular network, set at timeout (timeout %d ms)", TIMEOUT_NETWORK);
|
||||
// when using modems stack connect is synchronous
|
||||
enter_to_state(STATE_CONNECTED);
|
||||
} else {
|
||||
retry_state_or_fail();
|
||||
}
|
||||
bool is_running;
|
||||
_mutex.lock();
|
||||
current_state = _state;
|
||||
target_state = _target_state;
|
||||
is_running = _event_id != -1;
|
||||
_mutex.unlock();
|
||||
return is_running;
|
||||
}
|
||||
|
||||
void CellularStateMachine::event()
|
||||
{
|
||||
tr_debug("CellularStateMachine::event(): %s", get_state_string(_state));
|
||||
_event_timeout = -1;
|
||||
_is_retry = false;
|
||||
|
||||
switch (_state) {
|
||||
case STATE_INIT:
|
||||
_current_event = (nsapi_event_t)CellularDeviceReady;
|
||||
|
@ -612,26 +588,14 @@ void CellularStateMachine::event()
|
|||
_current_event = (nsapi_event_t)CellularAttachNetwork;
|
||||
state_attaching();
|
||||
break;
|
||||
case STATE_ACTIVATING_PDP_CONTEXT:
|
||||
_current_event = (nsapi_event_t)CellularActivatePDPContext;
|
||||
state_activating_pdp_context();
|
||||
break;
|
||||
case STATE_CONNECTING_NETWORK:
|
||||
_current_event = NSAPI_EVENT_CONNECTION_STATUS_CHANGE;
|
||||
state_connect_to_network();
|
||||
break;
|
||||
case STATE_CONNECTED:
|
||||
_current_event = NSAPI_EVENT_CONNECTION_STATUS_CHANGE;
|
||||
break;
|
||||
case STATE_DISCONNECTING:
|
||||
default:
|
||||
MBED_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
|
||||
if (_blocking && _target_state == _state && _cb_data.error == NSAPI_ERROR_OK) {
|
||||
if (_target_state == _state && _cb_data.error == NSAPI_ERROR_OK && !_is_retry) {
|
||||
tr_info("Target state reached: %s", get_state_string(_target_state));
|
||||
_stm_semaphore.release();
|
||||
_event_id = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -660,10 +624,6 @@ nsapi_error_t CellularStateMachine::start_dispatch()
|
|||
MBED_ASSERT(!_queue_thread);
|
||||
|
||||
_queue_thread = new rtos::Thread(osPriorityNormal, 2048);
|
||||
if (!_queue_thread) {
|
||||
stop();
|
||||
return NSAPI_ERROR_NO_MEMORY;
|
||||
}
|
||||
if (_queue_thread->start(callback(&_queue, &events::EventQueue::dispatch_forever)) != osOK) {
|
||||
stop();
|
||||
return NSAPI_ERROR_NO_MEMORY;
|
||||
|
@ -672,35 +632,24 @@ nsapi_error_t CellularStateMachine::start_dispatch()
|
|||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
void CellularStateMachine::attach(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb)
|
||||
void CellularStateMachine::set_cellular_callback(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb)
|
||||
{
|
||||
_event_status_cb = status_cb;
|
||||
}
|
||||
|
||||
nsapi_error_t CellularStateMachine::disconnect()
|
||||
{
|
||||
nsapi_error_t err = NSAPI_ERROR_OK;
|
||||
if (_network) {
|
||||
// set state to disconnecting
|
||||
_state = STATE_DISCONNECTING;
|
||||
err = _network->disconnect();
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
void CellularStateMachine::network_callback(nsapi_event_t ev, intptr_t ptr)
|
||||
void CellularStateMachine::cellular_event_changed(nsapi_event_t ev, intptr_t ptr)
|
||||
{
|
||||
cell_callback_data_t *data = (cell_callback_data_t*)ptr;
|
||||
if (ev >= NSAPI_EVENT_CELLULAR_STATUS_BASE && ev <= NSAPI_EVENT_CELLULAR_STATUS_END) {
|
||||
tr_debug("FSM: network_callback called with event: %d, err: %d, data: %d _state: %s", ev, data->error, data->status_data, get_state_string(_state));
|
||||
tr_debug("FSM: cellular_event_changed called with event: %d, err: %d, data: %d _state: %s", ev, data->error, data->status_data, get_state_string(_state));
|
||||
} else {
|
||||
tr_debug("FSM: network_callback called with event: %d, ptr: %d _state: %s", ev, ptr, get_state_string(_state));
|
||||
tr_debug("FSM: cellular_event_changed called with event: %d, ptr: %d _state: %s", ev, ptr, get_state_string(_state));
|
||||
}
|
||||
|
||||
if ((cellular_connection_status_t)ev == CellularRegistrationStatusChanged &&
|
||||
(_state == STATE_REGISTERING_NETWORK || _state == STATE_MANUAL_REGISTERING_NETWORK)) {
|
||||
// expect packet data so only these states are valid
|
||||
if (data->status_data == CellularNetwork::RegisteredHomeNetwork || data->status_data == CellularNetwork::RegisteredRoaming) {
|
||||
if ((data->status_data == CellularNetwork::RegisteredHomeNetwork || data->status_data == CellularNetwork::RegisteredRoaming) && data->error == NSAPI_ERROR_OK) {
|
||||
if (_plmn) {
|
||||
if (is_registered_to_plmn()) {
|
||||
if (!_plmn_network_found) {
|
||||
|
@ -715,30 +664,6 @@ void CellularStateMachine::network_callback(nsapi_event_t ev, intptr_t ptr)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_event_status_cb) {
|
||||
_event_status_cb(ev, ptr);
|
||||
}
|
||||
|
||||
// try to reconnect if we think that we are connected, automatic reconnection is on and we get event disconnected
|
||||
if (_automatic_reconnect && ev == NSAPI_EVENT_CONNECTION_STATUS_CHANGE && ptr == NSAPI_STATUS_DISCONNECTED &&
|
||||
_state == STATE_CONNECTED) {
|
||||
|
||||
tr_info("FSM: start automatic reconnect!");
|
||||
// call disconnect to set filehandle irq back to us, don't really care about return value.
|
||||
(void)_network->disconnect();
|
||||
|
||||
// start from registering phase as we might have been deregistered if there is no network
|
||||
if (_plmn) {
|
||||
continue_from_state(STATE_MANUAL_REGISTERING_NETWORK);
|
||||
} else {
|
||||
continue_from_state(STATE_REGISTERING_NETWORK);
|
||||
}
|
||||
|
||||
if (_event_status_cb) {
|
||||
_event_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_RECONNECTING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CellularStateMachine::ready_urc_cb()
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "EventQueue.h"
|
||||
#include "CellularNetwork.h"
|
||||
#include "CellularCommon.h"
|
||||
#include "Semaphore.h"
|
||||
#include "PlatformMutex.h"
|
||||
|
||||
namespace rtos {
|
||||
class Thread;
|
||||
|
@ -28,33 +28,28 @@ namespace rtos {
|
|||
|
||||
namespace mbed {
|
||||
|
||||
class UARTSerial;
|
||||
class CellularPower;
|
||||
class CellularSIM;
|
||||
class CellularDevice;
|
||||
|
||||
const int MAX_PIN_SIZE = 8;
|
||||
const int RETRY_ARRAY_SIZE = 10;
|
||||
|
||||
/** CellularStateMachine class
|
||||
*
|
||||
* Finite State Machine for connecting to cellular network.
|
||||
* By default automatic reconnecting is on. This means that when FSM gets the disconnected callback
|
||||
* it will try to connect automatically. Application can toggle this behavior with method set_automatic_reconnect(...)
|
||||
* Finite State Machine for attaching to cellular network. Used by CellularDevice.
|
||||
*/
|
||||
class CellularStateMachine {
|
||||
public:
|
||||
private:
|
||||
// friend of CellularDevice so that it's the only way to close/delete this class.
|
||||
friend class CellularDevice;
|
||||
/** Constructor
|
||||
*
|
||||
* @param device reference to CellularDevice
|
||||
* @param queue reference to queue used in state transitions
|
||||
* @param power power needed in first state. Can be also given with set_power but must be given before
|
||||
* calling run_to_state. Transfers ownership to this class.
|
||||
*/
|
||||
CellularStateMachine(CellularDevice &device, events::EventQueue &queue, CellularPower *power);
|
||||
CellularStateMachine(CellularDevice &device, events::EventQueue &queue);
|
||||
~CellularStateMachine();
|
||||
|
||||
public:
|
||||
/** Cellular connection states
|
||||
*/
|
||||
enum CellularState {
|
||||
|
@ -65,60 +60,17 @@ public:
|
|||
STATE_REGISTERING_NETWORK,
|
||||
STATE_MANUAL_REGISTERING_NETWORK,
|
||||
STATE_ATTACHING_NETWORK,
|
||||
STATE_ACTIVATING_PDP_CONTEXT,
|
||||
STATE_CONNECTING_NETWORK,
|
||||
STATE_CONNECTED,
|
||||
STATE_DISCONNECTING,
|
||||
STATE_MAX_FSM_STATE
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
/** Set the SIM interface. Transfers ownership to this class.
|
||||
/** Register cellular specific for status changes
|
||||
*
|
||||
* @param sim sim interface to be used to access sim services
|
||||
*/
|
||||
void set_sim(CellularSIM* sim);
|
||||
|
||||
/** Set the network interface. Transfers ownership to this class.
|
||||
*
|
||||
* @param nw network interface to be used for network services
|
||||
*/
|
||||
void set_network(CellularNetwork* nw);
|
||||
|
||||
/** Set the power interface. Transfers ownership to this class.
|
||||
*
|
||||
* @param pwr power interface for power handling
|
||||
*/
|
||||
void set_power(CellularPower* pwr);
|
||||
|
||||
/** By default run_to_state is synchronous. This method can toggle between sync/async.
|
||||
*
|
||||
*/
|
||||
void set_blocking(bool blocking);
|
||||
|
||||
/** Disconnects from the cellular network.
|
||||
*
|
||||
* @return NSAPI_ERROR_OK on success, negative code in case of failure
|
||||
*/
|
||||
nsapi_error_t disconnect();
|
||||
|
||||
/** By default automatic reconnecting is on. This means that when FSM gets the disconnected callback
|
||||
* it will try to connect automatically. By this method application can toggle this behavior.
|
||||
*
|
||||
* @param do_reconnect true for automatic reconnect, false to not reconnect automatically
|
||||
*/
|
||||
void set_automatic_reconnect(bool do_reconnect);
|
||||
|
||||
/** Register callback for status reporting
|
||||
*
|
||||
* The specified status callback function will be called on status changes
|
||||
* on the network. The parameters on the callback are the event type and
|
||||
* event-type dependent reason parameter.
|
||||
* The specified status callback function will be called on device status changes.
|
||||
* The parameters on the callback are the event type and event-type dependent reason parameter.
|
||||
*
|
||||
* @param status_cb The callback for status changes
|
||||
*/
|
||||
void attach(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb);
|
||||
void set_cellular_callback(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb);
|
||||
|
||||
/** Start event queue dispatching
|
||||
* @return see nsapi_error_t, 0 on success
|
||||
|
@ -135,16 +87,6 @@ public:
|
|||
*/
|
||||
nsapi_error_t run_to_state(CellularState state);
|
||||
|
||||
/** Set the Cellular network credentials
|
||||
*
|
||||
* Please check documentation of connect() for default behaviour of APN settings.
|
||||
*
|
||||
* @param apn Access point name
|
||||
* @param uname optionally, Username
|
||||
* @param pwd optionally, password
|
||||
*/
|
||||
nsapi_error_t set_credentials(const char *apn, const char *uname = 0, const char *pwd = 0);
|
||||
|
||||
/** Set cellular device SIM PIN code
|
||||
* @param sim_pin PIN code
|
||||
*/
|
||||
|
@ -176,6 +118,23 @@ public:
|
|||
* @return event queue
|
||||
*/
|
||||
events::EventQueue *get_queue() const;
|
||||
|
||||
/** Get the current status of the state machine. Thread safe.
|
||||
*
|
||||
* @param current_state
|
||||
* @param target_state
|
||||
* @return true if state machine is running, false is not
|
||||
*
|
||||
*/
|
||||
bool get_current_status(CellularStateMachine::CellularState ¤t_state, CellularStateMachine::CellularState &target_state);
|
||||
|
||||
/** CellularDevice updates about network events and cellular events
|
||||
*
|
||||
* @param ev Event type
|
||||
* @param ptr Event type specific data
|
||||
*/
|
||||
void cellular_event_changed(nsapi_event_t ev, intptr_t ptr);
|
||||
|
||||
private:
|
||||
bool power_on();
|
||||
bool open_sim();
|
||||
|
@ -191,18 +150,14 @@ private:
|
|||
void state_registering();
|
||||
void state_manual_registering_network();
|
||||
void state_attaching();
|
||||
void state_activating_pdp_context();
|
||||
void state_connect_to_network();
|
||||
void enter_to_state(CellularState state);
|
||||
void retry_state_or_fail();
|
||||
void network_callback(nsapi_event_t ev, intptr_t ptr);
|
||||
void continue_from_state(CellularState state);
|
||||
bool is_registered_to_plmn();
|
||||
|
||||
private:
|
||||
void report_failure(const char *msg);
|
||||
void event();
|
||||
void ready_urc_cb();
|
||||
void pre_event(CellularState state);
|
||||
|
||||
CellularDevice &_cellularDevice;
|
||||
CellularState _state;
|
||||
|
@ -217,7 +172,7 @@ private:
|
|||
events::EventQueue &_queue;
|
||||
rtos::Thread *_queue_thread;
|
||||
|
||||
char _sim_pin[MAX_PIN_SIZE + 1];
|
||||
const char *_sim_pin;
|
||||
int _retry_count;
|
||||
int _start_time;
|
||||
int _event_timeout;
|
||||
|
@ -228,11 +183,11 @@ private:
|
|||
const char *_plmn;
|
||||
bool _command_success;
|
||||
bool _plmn_network_found;
|
||||
bool _is_retry;
|
||||
cell_callback_data_t _cb_data;
|
||||
nsapi_event_t _current_event;
|
||||
bool _automatic_reconnect;
|
||||
bool _blocking;
|
||||
rtos::Semaphore _stm_semaphore;
|
||||
bool _active_context; // Is there any active context?
|
||||
PlatformMutex _mutex;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -17,10 +17,12 @@
|
|||
|
||||
#include "GEMALTO_CINTERION_CellularNetwork.h"
|
||||
#include "GEMALTO_CINTERION_Module.h"
|
||||
#include "AT_CellularInformation.h"
|
||||
#include "GEMALTO_CINTERION_CellularContext.h"
|
||||
#include "GEMALTO_CINTERION.h"
|
||||
#include "AT_CellularInformation.h"
|
||||
#include "CellularLog.h"
|
||||
|
||||
|
||||
using namespace mbed;
|
||||
using namespace events;
|
||||
|
||||
|
@ -39,6 +41,11 @@ AT_CellularNetwork *GEMALTO_CINTERION::open_network_impl(ATHandler &at)
|
|||
return new GEMALTO_CINTERION_CellularNetwork(at);
|
||||
}
|
||||
|
||||
AT_CellularContext *GEMALTO_CINTERION::create_context_impl(ATHandler &at, const char *apn, nsapi_ip_stack_t stack)
|
||||
{
|
||||
return new GEMALTO_CINTERION_CellularContext(at, this, apn, stack);
|
||||
}
|
||||
|
||||
nsapi_error_t GEMALTO_CINTERION::init_module(FileHandle *fh)
|
||||
{
|
||||
CellularInformation *information = open_information(fh);
|
||||
|
|
|
@ -30,8 +30,8 @@ public:
|
|||
|
||||
protected: // AT_CellularDevice
|
||||
virtual AT_CellularNetwork *open_network_impl(ATHandler &at);
|
||||
|
||||
public: // CellularDevice
|
||||
virtual AT_CellularContext *create_context_impl(ATHandler &at, const char *apn, nsapi_ip_stack_t stack);
|
||||
public:
|
||||
virtual nsapi_error_t init_module(FileHandle *fh);
|
||||
virtual uint16_t get_send_delay();
|
||||
};
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* 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 "GEMALTO_CINTERION_CellularContext.h"
|
||||
#include "GEMALTO_CINTERION_CellularStack.h"
|
||||
#include "GEMALTO_CINTERION_Module.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
GEMALTO_CINTERION_CellularContext::GEMALTO_CINTERION_CellularContext(ATHandler &at, CellularDevice *device,
|
||||
const char *apn, nsapi_ip_stack_t stack) : AT_CellularContext(at, device, apn, stack)
|
||||
{
|
||||
}
|
||||
|
||||
GEMALTO_CINTERION_CellularContext::~GEMALTO_CINTERION_CellularContext()
|
||||
{
|
||||
}
|
||||
|
||||
#if !NSAPI_PPP_AVAILABLE
|
||||
NetworkStack *GEMALTO_CINTERION_CellularContext::get_stack()
|
||||
{
|
||||
if (!_stack) {
|
||||
_stack = new GEMALTO_CINTERION_CellularStack(_at, _apn, _cid, _ip_stack_type);
|
||||
}
|
||||
return _stack;
|
||||
}
|
||||
#endif // NSAPI_PPP_AVAILABLE
|
||||
|
||||
bool GEMALTO_CINTERION_CellularContext::stack_type_supported(nsapi_ip_stack_t requested_stack)
|
||||
{
|
||||
#if NSAPI_PPP_AVAILABLE
|
||||
return (requested_stack == IPV4_STACK || requested_stack == IPV6_STACK);
|
||||
#else
|
||||
if (GEMALTO_CINTERION_Module::get_model() == GEMALTO_CINTERION_Module::ModelBGS2) {
|
||||
return (requested_stack == IPV4_STACK);
|
||||
}
|
||||
return (requested_stack == IPV4_STACK || requested_stack == IPV6_STACK);
|
||||
#endif
|
||||
}
|
||||
|
||||
} /* namespace mbed */
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef GEMALTO_CINTERION_CELLULARCONTEXT_H_
|
||||
#define GEMALTO_CINTERION_CELLULARCONTEXT_H_
|
||||
|
||||
#include "AT_CellularContext.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
class GEMALTO_CINTERION_CellularContext: public AT_CellularContext {
|
||||
public:
|
||||
GEMALTO_CINTERION_CellularContext(ATHandler &at, CellularDevice *device, const char *apn, nsapi_ip_stack_t stack);
|
||||
virtual ~GEMALTO_CINTERION_CellularContext();
|
||||
|
||||
protected:
|
||||
#if !NSAPI_PPP_AVAILABLE
|
||||
virtual NetworkStack *get_stack();
|
||||
#endif // NSAPI_PPP_AVAILABLE
|
||||
virtual bool stack_type_supported(nsapi_ip_stack_t requested_stack);
|
||||
};
|
||||
|
||||
} /* namespace mbed */
|
||||
|
||||
#endif // GEMALTO_CINTERION_CELLULARCONTEXT_H_
|
|
@ -16,7 +16,6 @@
|
|||
*/
|
||||
|
||||
#include "GEMALTO_CINTERION_CellularNetwork.h"
|
||||
#include "GEMALTO_CINTERION_CellularStack.h"
|
||||
#include "GEMALTO_CINTERION_Module.h"
|
||||
|
||||
using namespace mbed;
|
||||
|
@ -29,24 +28,6 @@ GEMALTO_CINTERION_CellularNetwork::~GEMALTO_CINTERION_CellularNetwork()
|
|||
{
|
||||
}
|
||||
|
||||
#if !NSAPI_PPP_AVAILABLE
|
||||
NetworkStack *GEMALTO_CINTERION_CellularNetwork::get_stack()
|
||||
{
|
||||
if (!_stack) {
|
||||
_stack = new GEMALTO_CINTERION_CellularStack(_at, _apn, _cid, _ip_stack_type);
|
||||
}
|
||||
return _stack;
|
||||
}
|
||||
#endif // NSAPI_PPP_AVAILABLE
|
||||
|
||||
bool GEMALTO_CINTERION_CellularNetwork::get_modem_stack_type(nsapi_ip_stack_t requested_stack)
|
||||
{
|
||||
if (GEMALTO_CINTERION_Module::get_model() == GEMALTO_CINTERION_Module::ModelBGS2) {
|
||||
return (requested_stack == IPV4_STACK);
|
||||
}
|
||||
return (requested_stack == IPV4_STACK || requested_stack == IPV6_STACK);
|
||||
}
|
||||
|
||||
AT_CellularNetwork::RegistrationMode GEMALTO_CINTERION_CellularNetwork::has_registration(RegistrationType reg_type)
|
||||
{
|
||||
if (GEMALTO_CINTERION_Module::get_model() == GEMALTO_CINTERION_Module::ModelEMS31) {
|
||||
|
|
|
@ -28,14 +28,7 @@ public:
|
|||
virtual ~GEMALTO_CINTERION_CellularNetwork();
|
||||
|
||||
protected:
|
||||
#if !NSAPI_PPP_AVAILABLE
|
||||
virtual NetworkStack *get_stack();
|
||||
#endif // NSAPI_PPP_AVAILABLE
|
||||
|
||||
virtual RegistrationMode has_registration(RegistrationType reg_type);
|
||||
|
||||
virtual bool get_modem_stack_type(nsapi_ip_stack_t requested_stack);
|
||||
|
||||
virtual nsapi_error_t set_access_technology_impl(RadioAccessTechnology opsAct);
|
||||
};
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#include "QUECTEL_BC95_CellularNetwork.h"
|
||||
#include "QUECTEL_BC95_CellularPower.h"
|
||||
#include "QUECTEL_BC95_CellularSIM.h"
|
||||
|
||||
#include "QUECTEL_BC95_CellularContext.h"
|
||||
#include "QUECTEL_BC95.h"
|
||||
|
||||
#define CONNECT_DELIM "\r\n"
|
||||
|
@ -59,3 +59,8 @@ AT_CellularSIM *QUECTEL_BC95::open_sim_impl(ATHandler &at)
|
|||
{
|
||||
return new QUECTEL_BC95_CellularSIM(at);
|
||||
}
|
||||
|
||||
AT_CellularContext *QUECTEL_BC95::create_context_impl(ATHandler &at, const char *apn, nsapi_ip_stack_t stack)
|
||||
{
|
||||
return new QUECTEL_BC95_CellularContext(at, this, apn, stack);
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ protected: // AT_CellularDevice
|
|||
virtual AT_CellularNetwork *open_network_impl(ATHandler &at);
|
||||
virtual AT_CellularPower *open_power_impl(ATHandler &at);
|
||||
virtual AT_CellularSIM *open_sim_impl(ATHandler &at);
|
||||
virtual AT_CellularContext *create_context_impl(ATHandler &at, const char *apn, nsapi_ip_stack_t stack);
|
||||
|
||||
public: // NetworkInterface
|
||||
void handle_urc(FileHandle *fh);
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* 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 "QUECTEL_BC95_CellularContext.h"
|
||||
#include "QUECTEL_BC95_CellularStack.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
QUECTEL_BC95_CellularContext::QUECTEL_BC95_CellularContext(ATHandler &at, CellularDevice *device, const char *apn,
|
||||
nsapi_ip_stack_t stack) : AT_CellularContext(at, device, apn, stack)
|
||||
{
|
||||
}
|
||||
|
||||
QUECTEL_BC95_CellularContext::~QUECTEL_BC95_CellularContext()
|
||||
{
|
||||
}
|
||||
|
||||
NetworkStack *QUECTEL_BC95_CellularContext::get_stack()
|
||||
{
|
||||
if (!_stack) {
|
||||
_stack = new QUECTEL_BC95_CellularStack(_at, _cid, _ip_stack_type);
|
||||
}
|
||||
return _stack;
|
||||
}
|
||||
|
||||
bool QUECTEL_BC95_CellularContext::get_modem_stack_type(nsapi_ip_stack_t requested_stack)
|
||||
{
|
||||
return requested_stack == IPV4_STACK ? true : false;
|
||||
}
|
||||
|
||||
} /* namespace mbed */
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef QUECTEL_BC95_CELLULARCONTEXT_H_
|
||||
#define QUECTEL_BC95_CELLULARCONTEXT_H_
|
||||
|
||||
#include "AT_CellularContext.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
class QUECTEL_BC95_CellularContext: public AT_CellularContext {
|
||||
public:
|
||||
QUECTEL_BC95_CellularContext(ATHandler &at, CellularDevice *device, const char *apn, nsapi_ip_stack_t stack);
|
||||
virtual ~QUECTEL_BC95_CellularContext();
|
||||
|
||||
protected:
|
||||
virtual NetworkStack *get_stack();
|
||||
virtual bool get_modem_stack_type(nsapi_ip_stack_t requested_stack);
|
||||
};
|
||||
|
||||
} /* namespace mbed */
|
||||
|
||||
#endif // QUECTEL_BC95_CELLULARCONTEXT_H_
|
|
@ -16,7 +16,6 @@
|
|||
*/
|
||||
|
||||
#include "QUECTEL_BC95_CellularNetwork.h"
|
||||
#include "QUECTEL_BC95_CellularStack.h"
|
||||
|
||||
using namespace mbed;
|
||||
|
||||
|
@ -29,19 +28,6 @@ QUECTEL_BC95_CellularNetwork::~QUECTEL_BC95_CellularNetwork()
|
|||
{
|
||||
}
|
||||
|
||||
NetworkStack *QUECTEL_BC95_CellularNetwork::get_stack()
|
||||
{
|
||||
if (!_stack) {
|
||||
_stack = new QUECTEL_BC95_CellularStack(_at, _cid, _ip_stack_type);
|
||||
}
|
||||
return _stack;
|
||||
}
|
||||
|
||||
bool QUECTEL_BC95_CellularNetwork::get_modem_stack_type(nsapi_ip_stack_t requested_stack)
|
||||
{
|
||||
return requested_stack == IPV4_STACK ? true : false;
|
||||
}
|
||||
|
||||
AT_CellularNetwork::RegistrationMode QUECTEL_BC95_CellularNetwork::has_registration(RegistrationType reg_tech)
|
||||
{
|
||||
return (reg_tech == C_EREG) ? RegistrationModeLAC : RegistrationModeDisable;
|
||||
|
|
|
@ -28,12 +28,7 @@ public:
|
|||
virtual ~QUECTEL_BC95_CellularNetwork();
|
||||
|
||||
protected:
|
||||
virtual NetworkStack *get_stack();
|
||||
|
||||
virtual nsapi_error_t set_access_technology_impl(RadioAccessTechnology opRat);
|
||||
|
||||
virtual bool get_modem_stack_type(nsapi_ip_stack_t requested_stack);
|
||||
|
||||
virtual RegistrationMode has_registration(RegistrationType reg_type);
|
||||
};
|
||||
} // namespace mbed
|
||||
|
|
|
@ -15,9 +15,12 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "QUECTEL/BG96/QUECTEL_BG96.h"
|
||||
#include "QUECTEL/BG96/QUECTEL_BG96_CellularNetwork.h"
|
||||
#include "QUECTEL/BG96/QUECTEL_BG96_CellularStack.h"
|
||||
#include "QUECTEL_BG96.h"
|
||||
#include "QUECTEL_BG96_CellularNetwork.h"
|
||||
#include "QUECTEL_BG96_CellularStack.h"
|
||||
#include "QUECTEL_BG96_CellularSIM.h"
|
||||
#include "QUECTEL_BG96_CellularPower.h"
|
||||
#include "QUECTEL_BG96_CellularContext.h"
|
||||
|
||||
using namespace mbed;
|
||||
using namespace events;
|
||||
|
@ -47,3 +50,19 @@ AT_CellularNetwork *QUECTEL_BG96::open_network_impl(ATHandler &at)
|
|||
{
|
||||
return new QUECTEL_BG96_CellularNetwork(at);
|
||||
}
|
||||
|
||||
AT_CellularSIM *QUECTEL_BG96::open_sim_impl(ATHandler &at)
|
||||
{
|
||||
return new QUECTEL_BG96_CellularSIM(at);
|
||||
}
|
||||
|
||||
AT_CellularPower *QUECTEL_BG96::open_power_impl(ATHandler &at)
|
||||
{
|
||||
return new QUECTEL_BG96_CellularPower(at);
|
||||
}
|
||||
|
||||
AT_CellularContext *QUECTEL_BG96::create_context_impl(ATHandler &at, const char *apn, nsapi_ip_stack_t stack)
|
||||
{
|
||||
return new QUECTEL_BG96_CellularContext(at, this, apn, stack);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,8 +29,10 @@ public:
|
|||
|
||||
protected: // AT_CellularDevice
|
||||
virtual AT_CellularNetwork *open_network_impl(ATHandler &at);
|
||||
|
||||
public: // NetworkInterface
|
||||
virtual AT_CellularSIM *open_sim_impl(ATHandler &at);
|
||||
virtual AT_CellularPower *open_power_impl(ATHandler &at);
|
||||
virtual AT_CellularContext *create_context_impl(ATHandler &at, const char *apn, nsapi_ip_stack_t stack);
|
||||
public:
|
||||
void handle_urc(FileHandle *fh);
|
||||
};
|
||||
} // namespace mbed
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* 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 "QUECTEL_BG96_CellularContext.h"
|
||||
#include "QUECTEL_BG96_CellularStack.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
QUECTEL_BG96_CellularContext::QUECTEL_BG96_CellularContext(ATHandler &at, CellularDevice *device, const char *apn,
|
||||
nsapi_ip_stack_t stack) : AT_CellularContext(at, device, apn, stack)
|
||||
{
|
||||
}
|
||||
|
||||
QUECTEL_BG96_CellularContext::~QUECTEL_BG96_CellularContext()
|
||||
{
|
||||
}
|
||||
|
||||
bool QUECTEL_BG96_CellularContext::stack_type_supported(nsapi_ip_stack_t stack_type)
|
||||
{
|
||||
if (stack_type == IPV4_STACK) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
NetworkStack *QUECTEL_BG96_CellularContext::get_stack()
|
||||
{
|
||||
if (!_stack) {
|
||||
_stack = new QUECTEL_BG96_CellularStack(_at, _cid, _ip_stack_type);
|
||||
}
|
||||
return _stack;
|
||||
}
|
||||
|
||||
nsapi_error_t QUECTEL_BG96_CellularContext::do_user_authentication()
|
||||
{
|
||||
if (_pwd && _uname) {
|
||||
_at.cmd_start("AT+QICSGP=");
|
||||
_at.write_int(_cid);
|
||||
_at.write_int(1); // IPv4
|
||||
_at.write_string(_apn);
|
||||
_at.write_string(_uname);
|
||||
_at.write_string(_pwd);
|
||||
_at.write_int(_authentication_type);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
if (_at.get_last_error() != NSAPI_ERROR_OK) {
|
||||
return NSAPI_ERROR_AUTH_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
} /* namespace mbed */
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef QUECTEL_BG96_CELLULARCONTEXT_H_
|
||||
#define QUECTEL_BG96_CELLULARCONTEXT_H_
|
||||
|
||||
#include "AT_CellularContext.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
class QUECTEL_BG96_CellularContext: public AT_CellularContext {
|
||||
public:
|
||||
QUECTEL_BG96_CellularContext(ATHandler &at, CellularDevice *device, const char *apn, nsapi_ip_stack_t stack);
|
||||
virtual ~QUECTEL_BG96_CellularContext();
|
||||
|
||||
protected:
|
||||
virtual bool stack_type_supported(nsapi_ip_stack_t stack_type);
|
||||
virtual NetworkStack *get_stack();
|
||||
virtual nsapi_error_t do_user_authentication();
|
||||
};
|
||||
|
||||
} /* namespace mbed */
|
||||
|
||||
#endif // QUECTEL_BG96_CELLULARCONTEXT_H_
|
|
@ -28,23 +28,6 @@ QUECTEL_BG96_CellularNetwork::~QUECTEL_BG96_CellularNetwork()
|
|||
{
|
||||
}
|
||||
|
||||
bool QUECTEL_BG96_CellularNetwork::get_modem_stack_type(nsapi_ip_stack_t requested_stack)
|
||||
{
|
||||
if (requested_stack == IPV4_STACK) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
NetworkStack *QUECTEL_BG96_CellularNetwork::get_stack()
|
||||
{
|
||||
if (!_stack) {
|
||||
_stack = new QUECTEL_BG96_CellularStack(_at, _cid, _ip_stack_type);
|
||||
}
|
||||
return _stack;
|
||||
}
|
||||
|
||||
nsapi_error_t QUECTEL_BG96_CellularNetwork::set_access_technology_impl(RadioAccessTechnology opsAct)
|
||||
{
|
||||
_at.lock();
|
||||
|
@ -89,22 +72,3 @@ nsapi_error_t QUECTEL_BG96_CellularNetwork::set_access_technology_impl(RadioAcce
|
|||
|
||||
return _at.unlock_return_error();
|
||||
}
|
||||
|
||||
nsapi_error_t QUECTEL_BG96_CellularNetwork::do_user_authentication()
|
||||
{
|
||||
if (_pwd && _uname) {
|
||||
_at.cmd_start("AT+QICSGP=");
|
||||
_at.write_int(_cid);
|
||||
_at.write_int(1); // IPv4
|
||||
_at.write_string(_apn);
|
||||
_at.write_string(_uname);
|
||||
_at.write_string(_pwd);
|
||||
_at.write_int(_authentication_type);
|
||||
_at.cmd_stop_read_resp();
|
||||
if (_at.get_last_error() != NSAPI_ERROR_OK) {
|
||||
return NSAPI_ERROR_AUTH_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
|
|
@ -28,13 +28,7 @@ public:
|
|||
virtual ~QUECTEL_BG96_CellularNetwork();
|
||||
|
||||
protected:
|
||||
virtual NetworkStack *get_stack();
|
||||
|
||||
virtual nsapi_error_t set_access_technology_impl(RadioAccessTechnology opRat);
|
||||
|
||||
virtual bool get_modem_stack_type(nsapi_ip_stack_t requested_stack);
|
||||
|
||||
virtual nsapi_error_t do_user_authentication();
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
|
|
@ -15,9 +15,10 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "QUECTEL/UG96/QUECTEL_UG96.h"
|
||||
#include "QUECTEL/UG96/QUECTEL_UG96_CellularNetwork.h"
|
||||
#include "QUECTEL/UG96/QUECTEL_UG96_CellularPower.h"
|
||||
#include "QUECTEL_UG96.h"
|
||||
#include "QUECTEL_UG96_CellularNetwork.h"
|
||||
#include "QUECTEL_UG96_CellularPower.h"
|
||||
#include "QUECTEL_UG96_CellularContext.h"
|
||||
|
||||
using namespace mbed;
|
||||
using namespace events;
|
||||
|
@ -46,3 +47,8 @@ AT_CellularPower *QUECTEL_UG96::open_power_impl(ATHandler &at)
|
|||
{
|
||||
return new QUECTEL_UG96_CellularPower(at);
|
||||
}
|
||||
|
||||
AT_CellularContext *QUECTEL_UG96::create_context_impl(ATHandler &at, const char *apn, nsapi_ip_stack_t stack)
|
||||
{
|
||||
return new QUECTEL_UG96_CellularContext(at, this, apn, stack);
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ public:
|
|||
protected: // AT_CellularDevice
|
||||
virtual AT_CellularNetwork *open_network_impl(ATHandler &at);
|
||||
virtual AT_CellularPower *open_power_impl(ATHandler &at);
|
||||
virtual AT_CellularContext *create_context_impl(ATHandler &at, const char *apn, nsapi_ip_stack_t stack);
|
||||
|
||||
public: // NetworkInterface
|
||||
void handle_urc(FileHandle *fh);
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* 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 "QUECTEL_UG96_CellularContext.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
QUECTEL_UG96_CellularContext::QUECTEL_UG96_CellularContext(ATHandler &at, CellularDevice *device, const char *apn,
|
||||
nsapi_ip_stack_t stack) : AT_CellularContext(at, device, apn, stack)
|
||||
{
|
||||
}
|
||||
|
||||
QUECTEL_UG96_CellularContext::~QUECTEL_UG96_CellularContext()
|
||||
{
|
||||
}
|
||||
|
||||
bool QUECTEL_UG96_CellularContext::stack_type_supported(nsapi_ip_stack_t requested_stack)
|
||||
{
|
||||
return requested_stack == IPV4_STACK ? true : false;
|
||||
}
|
||||
|
||||
nsapi_error_t QUECTEL_UG96_CellularContext::do_user_authentication()
|
||||
{
|
||||
if (_pwd && _uname) {
|
||||
_at.cmd_start("AT+QICSGP=");
|
||||
_at.write_int(_cid);
|
||||
_at.write_int(1); // context type 1=IPv4
|
||||
_at.write_string(_apn);
|
||||
_at.write_string(_uname);
|
||||
_at.write_string(_pwd);
|
||||
_at.write_int(_authentication_type);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
if (_at.get_last_error() != NSAPI_ERROR_OK) {
|
||||
return NSAPI_ERROR_AUTH_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
} /* namespace mbed */
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef QUECTEL_UG96_CELLULARCONTEXT_H_
|
||||
#define QUECTEL_UG96_CELLULARCONTEXT_H_
|
||||
|
||||
#include "AT_CellularContext.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
class QUECTEL_UG96_CellularContext: public AT_CellularContext {
|
||||
public:
|
||||
QUECTEL_UG96_CellularContext(ATHandler &at, CellularDevice *device, const char *apn, nsapi_ip_stack_t stack);
|
||||
virtual ~QUECTEL_UG96_CellularContext();
|
||||
|
||||
protected:
|
||||
virtual bool stack_type_supported(nsapi_ip_stack_t requested_stack);
|
||||
virtual nsapi_error_t do_user_authentication();
|
||||
};
|
||||
|
||||
} /* namespace mbed */
|
||||
|
||||
#endif // QUECTEL_UG96_CELLULARCONTEXT_H_
|
|
@ -15,7 +15,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "QUECTEL/UG96/QUECTEL_UG96_CellularNetwork.h"
|
||||
#include "QUECTEL_UG96_CellularNetwork.h"
|
||||
|
||||
using namespace mbed;
|
||||
|
||||
|
@ -27,11 +27,6 @@ QUECTEL_UG96_CellularNetwork::~QUECTEL_UG96_CellularNetwork()
|
|||
{
|
||||
}
|
||||
|
||||
bool QUECTEL_UG96_CellularNetwork::get_modem_stack_type(nsapi_ip_stack_t requested_stack)
|
||||
{
|
||||
return requested_stack == IPV4_STACK ? true : false;
|
||||
}
|
||||
|
||||
AT_CellularNetwork::RegistrationMode QUECTEL_UG96_CellularNetwork::has_registration(RegistrationType reg_type)
|
||||
{
|
||||
return (reg_type == C_REG || reg_type == C_GREG) ? RegistrationModeLAC : RegistrationModeDisable;
|
||||
|
@ -42,24 +37,3 @@ nsapi_error_t QUECTEL_UG96_CellularNetwork::set_access_technology_impl(RadioAcce
|
|||
_op_act = RAT_UNKNOWN;
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
nsapi_error_t QUECTEL_UG96_CellularNetwork::do_user_authentication()
|
||||
{
|
||||
if (_pwd && _uname) {
|
||||
_at.cmd_start("AT+QICSGP=");
|
||||
_at.write_int(_cid);
|
||||
_at.write_int(1); // context type 1=IPv4
|
||||
_at.write_string(_apn);
|
||||
_at.write_string(_uname);
|
||||
_at.write_string(_pwd);
|
||||
_at.write_int(_authentication_type);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
if (_at.get_last_error() != NSAPI_ERROR_OK) {
|
||||
return NSAPI_ERROR_AUTH_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
|
|
@ -28,13 +28,8 @@ public:
|
|||
virtual ~QUECTEL_UG96_CellularNetwork();
|
||||
|
||||
protected:
|
||||
virtual bool get_modem_stack_type(nsapi_ip_stack_t requested_stack);
|
||||
|
||||
virtual RegistrationMode has_registration(RegistrationType rat);
|
||||
|
||||
virtual nsapi_error_t set_access_technology_impl(RadioAccessTechnology opRat);
|
||||
|
||||
virtual nsapi_error_t do_user_authentication();
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "TELIT_HE910.h"
|
||||
#include "TELIT_HE910_CellularPower.h"
|
||||
#include "TELIT_HE910_CellularNetwork.h"
|
||||
#include "TELIT_HE910_CellularContext.h"
|
||||
|
||||
using namespace mbed;
|
||||
using namespace events;
|
||||
|
@ -47,6 +48,11 @@ AT_CellularPower *TELIT_HE910::open_power_impl(ATHandler &at)
|
|||
return new TELIT_HE910_CellularPower(at);
|
||||
}
|
||||
|
||||
AT_CellularContext *TELIT_HE910::create_context_impl(ATHandler &at, const char *apn, nsapi_ip_stack_t stack)
|
||||
{
|
||||
return new TELIT_HE910_CellularContext(at, this, apn, stack);
|
||||
}
|
||||
|
||||
uint16_t TELIT_HE910::get_send_delay() const
|
||||
{
|
||||
return DEFAULT_DELAY_BETWEEN_AT_COMMANDS;
|
||||
|
|
|
@ -33,6 +33,7 @@ public:
|
|||
protected: // AT_CellularDevice
|
||||
virtual AT_CellularNetwork *open_network_impl(ATHandler &at);
|
||||
virtual AT_CellularPower *open_power_impl(ATHandler &at);
|
||||
virtual AT_CellularContext *create_context_impl(ATHandler &at, const char *apn, nsapi_ip_stack_t stack);
|
||||
|
||||
public: // from CellularDevice
|
||||
virtual uint16_t get_send_delay() const;
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* 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 "TELIT_HE910_CellularContext.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
TELIT_HE910_CellularContext::TELIT_HE910_CellularContext(ATHandler &at, CellularDevice *device, const char *apn,
|
||||
nsapi_ip_stack_t stack) : AT_CellularContext(at, device, apn, stack)
|
||||
{
|
||||
}
|
||||
|
||||
TELIT_HE910_CellularContext::~TELIT_HE910_CellularContext()
|
||||
{
|
||||
}
|
||||
|
||||
bool TELIT_HE910_CellularContext::stack_type_supported(nsapi_ip_stack_t requested_stack)
|
||||
{
|
||||
return requested_stack == IPV4_STACK || requested_stack == IPV6_STACK;
|
||||
}
|
||||
|
||||
} /* namespace mbed */
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef TELIT_HE910_CELLULARCONTEXT_H_
|
||||
#define TELIT_HE910_CELLULARCONTEXT_H_
|
||||
|
||||
#include "AT_CellularContext.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
class TELIT_HE910_CellularContext: public AT_CellularContext {
|
||||
public:
|
||||
TELIT_HE910_CellularContext(ATHandler &at, CellularDevice *device, const char *apn, nsapi_ip_stack_t stack);
|
||||
virtual ~TELIT_HE910_CellularContext();
|
||||
|
||||
protected:
|
||||
virtual bool stack_type_supported(nsapi_ip_stack_t requested_stack);
|
||||
};
|
||||
|
||||
} /* namespace mbed */
|
||||
|
||||
#endif // TELIT_HE910_CELLULARCONTEXT_H_
|
|
@ -27,11 +27,6 @@ TELIT_HE910_CellularNetwork::~TELIT_HE910_CellularNetwork()
|
|||
{
|
||||
}
|
||||
|
||||
bool TELIT_HE910_CellularNetwork::get_modem_stack_type(nsapi_ip_stack_t requested_stack)
|
||||
{
|
||||
return requested_stack == IPV4_STACK ? true : false;
|
||||
}
|
||||
|
||||
AT_CellularNetwork::RegistrationMode TELIT_HE910_CellularNetwork::has_registration(RegistrationType reg_type)
|
||||
{
|
||||
return (reg_type == C_REG || reg_type == C_GREG) ? RegistrationModeLAC : RegistrationModeDisable;
|
||||
|
|
|
@ -28,11 +28,7 @@ public:
|
|||
virtual ~TELIT_HE910_CellularNetwork();
|
||||
|
||||
protected:
|
||||
|
||||
virtual bool get_modem_stack_type(nsapi_ip_stack_t requested_stack);
|
||||
|
||||
virtual RegistrationMode has_registration(RegistrationType rat);
|
||||
|
||||
virtual nsapi_error_t set_access_technology_impl(RadioAccessTechnology opRat);
|
||||
};
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "UBLOX_AT.h"
|
||||
#include "UBLOX_AT_CellularNetwork.h"
|
||||
#include "UBLOX_AT_CellularPower.h"
|
||||
#include "UBLOX_AT_CellularContext.h"
|
||||
|
||||
using namespace mbed;
|
||||
using namespace events;
|
||||
|
@ -49,3 +50,8 @@ AT_CellularPower *UBLOX_AT::open_power_impl(ATHandler &at)
|
|||
{
|
||||
return new UBLOX_AT_CellularPower(at);
|
||||
}
|
||||
|
||||
AT_CellularContext *UBLOX_AT::create_context_impl(ATHandler &at, const char *apn, nsapi_ip_stack_t stack)
|
||||
{
|
||||
return new UBLOX_AT_CellularContext(at, this, apn, stack);
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ public:
|
|||
protected: // AT_CellularDevice
|
||||
virtual AT_CellularNetwork *open_network_impl(ATHandler &at);
|
||||
virtual AT_CellularPower *open_power_impl(ATHandler &at);
|
||||
|
||||
virtual AT_CellularContext *create_context_impl(ATHandler &at, const char *apn, nsapi_ip_stack_t stack);
|
||||
public: // NetworkInterface
|
||||
void handle_urc(FileHandle *fh);
|
||||
};
|
||||
|
|
|
@ -0,0 +1,286 @@
|
|||
/*
|
||||
* 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 "UBLOX_AT_CellularContext.h"
|
||||
#include "UBLOX_AT_CellularStack.h"
|
||||
#include "APN_db.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
UBLOX_AT_CellularContext::UBLOX_AT_CellularContext(ATHandler &at, CellularDevice *device, const char *apn,
|
||||
nsapi_ip_stack_t stack) : AT_CellularContext(at, device, apn, stack)
|
||||
{
|
||||
// The authentication to use
|
||||
_auth = NSAPI_SECURITY_UNKNOWN;
|
||||
}
|
||||
|
||||
UBLOX_AT_CellularContext::~UBLOX_AT_CellularContext()
|
||||
{
|
||||
}
|
||||
|
||||
NetworkStack *UBLOX_AT_CellularContext::get_stack()
|
||||
{
|
||||
if (!_stack) {
|
||||
_stack = new UBLOX_AT_CellularStack(_at, _cid, _ip_stack_type);
|
||||
}
|
||||
return _stack;
|
||||
}
|
||||
|
||||
bool UBLOX_AT_CellularContext::stack_type_supported(nsapi_ip_stack_t requested_stack)
|
||||
{
|
||||
return requested_stack == IPV4_STACK ? true : false;
|
||||
}
|
||||
|
||||
void UBLOX_AT_CellularContext::do_connect()
|
||||
{
|
||||
_at.lock();
|
||||
_cb_data.error = NSAPI_ERROR_NO_CONNECTION;
|
||||
|
||||
// Attempt to establish a connection
|
||||
#ifdef TARGET_UBLOX_C030_R410M
|
||||
_cb_data.error = NSAPI_ERROR_OK;
|
||||
#else
|
||||
_cb_data.error = open_data_channel();
|
||||
#endif
|
||||
if (_cb_data.error != NSAPI_ERROR_OK) {
|
||||
// If new PSD context was created and failed to activate, delete it
|
||||
if (_new_context_set) {
|
||||
disconnect_modem_stack();
|
||||
}
|
||||
_connect_status = NSAPI_STATUS_DISCONNECTED;
|
||||
} else {
|
||||
_connect_status = NSAPI_STATUS_GLOBAL_UP;
|
||||
}
|
||||
_at.unlock();
|
||||
|
||||
if (_status_cb) {
|
||||
call_network_cb(_connect_status);
|
||||
}
|
||||
}
|
||||
|
||||
nsapi_error_t UBLOX_AT_CellularContext::open_data_channel()
|
||||
{
|
||||
bool success = false;
|
||||
int active = 0;
|
||||
char * config = NULL;
|
||||
nsapi_error_t err = NSAPI_ERROR_NO_CONNECTION;
|
||||
char imsi[MAX_IMSI_LENGTH+1];
|
||||
|
||||
// do check for stack to validate that we have support for stack
|
||||
_stack = get_stack();
|
||||
if (!_stack) {
|
||||
return err;
|
||||
}
|
||||
|
||||
_at.cmd_start("AT+UPSND=" PROFILE ",8");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start("+UPSND:");
|
||||
_at.read_int();
|
||||
_at.read_int();
|
||||
active = _at.read_int();
|
||||
_at.resp_stop();
|
||||
|
||||
if (active == 0) {
|
||||
// If the caller hasn't entered an APN, try to find it
|
||||
if (_apn == NULL) {
|
||||
err = get_imsi(imsi);
|
||||
if (err == NSAPI_ERROR_OK) {
|
||||
config = (char*)apnconfig(imsi);
|
||||
}
|
||||
}
|
||||
|
||||
// Attempt to connect
|
||||
do {
|
||||
get_next_credentials(&config);
|
||||
if(_uname && _pwd) {
|
||||
_auth = (*_uname && *_pwd) ? _auth : NSAPI_SECURITY_NONE;
|
||||
} else {
|
||||
_auth = NSAPI_SECURITY_NONE;
|
||||
}
|
||||
success = activate_profile(_apn, _uname, _pwd);
|
||||
} while (!success && config && *config);
|
||||
} else {
|
||||
// If the profile is already active, we're good
|
||||
success = true;
|
||||
}
|
||||
|
||||
err = (_at.get_last_error() == NSAPI_ERROR_OK) ? NSAPI_ERROR_OK : NSAPI_ERROR_NO_CONNECTION;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
bool UBLOX_AT_CellularContext::activate_profile(const char* apn,
|
||||
const char* username,
|
||||
const char* password)
|
||||
{
|
||||
bool activated = false;
|
||||
bool success = false;
|
||||
|
||||
// Set up the APN
|
||||
if (apn) {
|
||||
success = false;
|
||||
_at.cmd_start("AT+UPSD=0,1,");
|
||||
_at.write_string(apn);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
|
||||
if (_at.get_last_error() == NSAPI_ERROR_OK) {
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
// Set up the UserName
|
||||
if (success && username) {
|
||||
success = false;
|
||||
_at.cmd_start("AT+UPSD=" PROFILE ",2,");
|
||||
_at.write_string(username);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
|
||||
if (_at.get_last_error() == NSAPI_ERROR_OK) {
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
// Set up the Password
|
||||
if (success && password) {
|
||||
success = false;
|
||||
_at.cmd_start("AT+UPSD=" PROFILE ",3,");
|
||||
_at.write_string(password);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
|
||||
if (_at.get_last_error() == NSAPI_ERROR_OK) {
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (success) {
|
||||
_at.cmd_start("AT+UPSD=" PROFILE ",7,\"0.0.0.0\"");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
|
||||
// Set up the authentication protocol
|
||||
// 0 = none
|
||||
// 1 = PAP (Password Authentication Protocol)
|
||||
// 2 = CHAP (Challenge Handshake Authentication Protocol)
|
||||
for (int protocol = nsapi_security_to_modem_security(NSAPI_SECURITY_NONE);
|
||||
success && (protocol <= nsapi_security_to_modem_security(NSAPI_SECURITY_CHAP)); protocol++) {
|
||||
if ((_auth == NSAPI_SECURITY_UNKNOWN) || (nsapi_security_to_modem_security(_auth) == protocol)) {
|
||||
_at.cmd_start("AT+UPSD=0,6,");
|
||||
_at.write_int(protocol);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
|
||||
if (_at.get_last_error() == NSAPI_ERROR_OK) {
|
||||
// Activate, wait upto 30 seconds for the connection to be made
|
||||
_at.set_at_timeout(30000);
|
||||
_at.cmd_start("AT+UPSDA=0,3");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
_at.restore_at_timeout();
|
||||
|
||||
if (_at.get_last_error() == NSAPI_ERROR_OK) {
|
||||
activated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return activated;
|
||||
}
|
||||
|
||||
// Convert nsapi_security_t to the modem security numbers
|
||||
int UBLOX_AT_CellularContext::nsapi_security_to_modem_security(nsapi_security_t nsapi_security)
|
||||
{
|
||||
int modem_security = 3;
|
||||
|
||||
switch (nsapi_security) {
|
||||
case NSAPI_SECURITY_NONE:
|
||||
modem_security = 0;
|
||||
break;
|
||||
case NSAPI_SECURITY_PAP:
|
||||
modem_security = 1;
|
||||
break;
|
||||
case NSAPI_SECURITY_CHAP:
|
||||
modem_security = 2;
|
||||
break;
|
||||
case NSAPI_SECURITY_UNKNOWN:
|
||||
modem_security = 3;
|
||||
break;
|
||||
default:
|
||||
modem_security = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
return modem_security;
|
||||
}
|
||||
|
||||
// Disconnect the on board IP stack of the modem.
|
||||
bool UBLOX_AT_CellularContext::disconnect_modem_stack()
|
||||
{
|
||||
bool success = false;
|
||||
|
||||
if (get_ip_address() != NULL) {
|
||||
_at.cmd_start("AT+UPSDA=" PROFILE ",4");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
|
||||
if (_at.get_last_error() == NSAPI_ERROR_OK) {
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
nsapi_error_t UBLOX_AT_CellularContext::get_imsi(char* imsi)
|
||||
{
|
||||
_at.lock();
|
||||
_at.cmd_start("AT+CIMI");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
int len = _at.read_string(imsi, MAX_IMSI_LENGTH);
|
||||
if (len > 0) {
|
||||
imsi[len] = '\0';
|
||||
}
|
||||
_at.resp_stop();
|
||||
|
||||
return _at.unlock_return_error();
|
||||
}
|
||||
|
||||
// Get the next set of credentials, based on IMSI.
|
||||
void UBLOX_AT_CellularContext::get_next_credentials(char ** config)
|
||||
{
|
||||
if (*config) {
|
||||
_apn = _APN_GET(*config);
|
||||
_uname = _APN_GET(*config);
|
||||
_pwd = _APN_GET(*config);
|
||||
}
|
||||
}
|
||||
|
||||
const char *UBLOX_AT_CellularContext::get_gateway()
|
||||
{
|
||||
return get_ip_address();
|
||||
}
|
||||
|
||||
} /* namespace mbed */
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef UBLOX_AT_CELLULARCONTEXT_H_
|
||||
#define UBLOX_AT_CELLULARCONTEXT_H_
|
||||
|
||||
#include "AT_CellularContext.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
class UBLOX_AT_CellularContext: public AT_CellularContext {
|
||||
public:
|
||||
UBLOX_AT_CellularContext(ATHandler &at, CellularDevice *device, const char *apn, nsapi_ip_stack_t stack);
|
||||
virtual ~UBLOX_AT_CellularContext();
|
||||
|
||||
virtual void do_connect();
|
||||
virtual const char *get_gateway();
|
||||
|
||||
protected:
|
||||
virtual NetworkStack *get_stack();
|
||||
virtual bool stack_type_supported(nsapi_ip_stack_t requested_stack);
|
||||
|
||||
private:
|
||||
|
||||
/** Length of IMSI buffer.
|
||||
*/
|
||||
static const int MAX_IMSI_LENGTH = 15;
|
||||
|
||||
/** The type of authentication to use.
|
||||
*/
|
||||
nsapi_security_t _auth;
|
||||
|
||||
/** Connect the on board IP stack of the modem.
|
||||
*
|
||||
* @return True if successful, otherwise false.
|
||||
*/
|
||||
nsapi_error_t open_data_channel();
|
||||
|
||||
/** Activate one of the on-board modem's connection profiles.
|
||||
*
|
||||
* @param apn The APN to use.
|
||||
* @param username The user name to use.
|
||||
* @param password The password to use.
|
||||
* @param auth The authentication method to use
|
||||
* (NSAPI_SECURITY_NONE, NSAPI_SECURITY_PAP,
|
||||
* NSAPI_SECURITY_CHAP or NSAPI_SECURITY_UNKNOWN).
|
||||
* @return True if successful, otherwise false.
|
||||
*/
|
||||
bool activate_profile(const char* apn, const char* username, const char* password);
|
||||
|
||||
/** Convert nsapi_security_t to the modem security numbers.
|
||||
*
|
||||
* @param nsapi_security Security protocol.
|
||||
* @return Modem security numbers.
|
||||
*/
|
||||
int nsapi_security_to_modem_security(nsapi_security_t nsapi_security);
|
||||
|
||||
/** Disconnect the on board IP stack of the modem.
|
||||
*
|
||||
* @return True if successful, otherwise false.
|
||||
*/
|
||||
bool disconnect_modem_stack();
|
||||
|
||||
/** Read IMSI of modem.
|
||||
*/
|
||||
nsapi_error_t get_imsi(char* imsi);
|
||||
|
||||
/** Get the next set of credentials from the database.
|
||||
*/
|
||||
void get_next_credentials(char ** config);
|
||||
};
|
||||
|
||||
} /* namespace mbed */
|
||||
|
||||
#endif // UBLOX_AT_CELLULARCONTEXT_H_
|
|
@ -16,15 +16,12 @@
|
|||
*/
|
||||
|
||||
#include "UBLOX_AT_CellularNetwork.h"
|
||||
#include "UBLOX_AT_CellularStack.h"
|
||||
|
||||
using namespace mbed;
|
||||
|
||||
UBLOX_AT_CellularNetwork::UBLOX_AT_CellularNetwork(ATHandler &atHandler) : AT_CellularNetwork(atHandler)
|
||||
{
|
||||
_op_act = RAT_UNKNOWN;
|
||||
// The authentication to use
|
||||
_auth = NSAPI_SECURITY_UNKNOWN;
|
||||
}
|
||||
|
||||
UBLOX_AT_CellularNetwork::~UBLOX_AT_CellularNetwork()
|
||||
|
@ -34,19 +31,6 @@ UBLOX_AT_CellularNetwork::~UBLOX_AT_CellularNetwork()
|
|||
}
|
||||
}
|
||||
|
||||
NetworkStack *UBLOX_AT_CellularNetwork::get_stack()
|
||||
{
|
||||
if (!_stack) {
|
||||
_stack = new UBLOX_AT_CellularStack(_at, _cid, _ip_stack_type);
|
||||
}
|
||||
return _stack;
|
||||
}
|
||||
|
||||
bool UBLOX_AT_CellularNetwork::get_modem_stack_type(nsapi_ip_stack_t requested_stack)
|
||||
{
|
||||
return requested_stack == IPV4_STACK ? true : false;
|
||||
}
|
||||
|
||||
AT_CellularNetwork::RegistrationMode UBLOX_AT_CellularNetwork::has_registration(RegistrationType reg_type)
|
||||
{
|
||||
return (reg_type == C_REG || reg_type == C_GREG) ? RegistrationModeLAC : RegistrationModeDisable;
|
||||
|
@ -85,230 +69,3 @@ nsapi_error_t UBLOX_AT_CellularNetwork::set_access_technology_impl(RadioAccessTe
|
|||
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
nsapi_error_t UBLOX_AT_CellularNetwork::connect()
|
||||
{
|
||||
_at.lock();
|
||||
nsapi_error_t err = NSAPI_ERROR_NO_CONNECTION;
|
||||
|
||||
// Attempt to establish a connection
|
||||
#ifdef TARGET_UBLOX_C030_R410M
|
||||
err = NSAPI_ERROR_OK;
|
||||
#else
|
||||
err = open_data_channel();
|
||||
#endif
|
||||
if (err != NSAPI_ERROR_OK) {
|
||||
// If new PSD context was created and failed to activate, delete it
|
||||
if (_new_context_set) {
|
||||
disconnect_modem_stack();
|
||||
}
|
||||
_connect_status = NSAPI_STATUS_DISCONNECTED;
|
||||
} else {
|
||||
_connect_status = NSAPI_STATUS_GLOBAL_UP;
|
||||
}
|
||||
_at.unlock();
|
||||
|
||||
if (_connection_status_cb) {
|
||||
_connection_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, _connect_status);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
nsapi_error_t UBLOX_AT_CellularNetwork::open_data_channel()
|
||||
{
|
||||
bool success = false;
|
||||
int active = 0;
|
||||
char *config = NULL;
|
||||
nsapi_error_t err = NSAPI_ERROR_NO_CONNECTION;
|
||||
char imsi[MAX_IMSI_LENGTH + 1];
|
||||
|
||||
// do check for stack to validate that we have support for stack
|
||||
_stack = get_stack();
|
||||
if (!_stack) {
|
||||
return err;
|
||||
}
|
||||
|
||||
_at.cmd_start("AT+UPSND=" PROFILE ",8");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start("+UPSND:");
|
||||
_at.read_int();
|
||||
_at.read_int();
|
||||
active = _at.read_int();
|
||||
_at.resp_stop();
|
||||
|
||||
if (active == 0) {
|
||||
// If the caller hasn't entered an APN, try to find it
|
||||
if (_apn == NULL) {
|
||||
err = get_imsi(imsi);
|
||||
if (err == NSAPI_ERROR_OK) {
|
||||
config = (char *)apnconfig(imsi);
|
||||
}
|
||||
}
|
||||
|
||||
// Attempt to connect
|
||||
do {
|
||||
get_next_credentials(&config);
|
||||
if (_uname && _pwd) {
|
||||
_auth = (*_uname && *_pwd) ? _auth : NSAPI_SECURITY_NONE;
|
||||
} else {
|
||||
_auth = NSAPI_SECURITY_NONE;
|
||||
}
|
||||
success = activate_profile(_apn, _uname, _pwd);
|
||||
} while (!success && config && *config);
|
||||
} else {
|
||||
// If the profile is already active, we're good
|
||||
success = true;
|
||||
}
|
||||
|
||||
err = (_at.get_last_error() == NSAPI_ERROR_OK) ? NSAPI_ERROR_OK : NSAPI_ERROR_NO_CONNECTION;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
bool UBLOX_AT_CellularNetwork::activate_profile(const char *apn,
|
||||
const char *username,
|
||||
const char *password)
|
||||
{
|
||||
bool activated = false;
|
||||
bool success = false;
|
||||
|
||||
// Set up the APN
|
||||
if (apn) {
|
||||
success = false;
|
||||
_at.cmd_start("AT+UPSD=0,1,");
|
||||
_at.write_string(apn);
|
||||
_at.cmd_stop_read_resp();
|
||||
|
||||
if (_at.get_last_error() == NSAPI_ERROR_OK) {
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
// Set up the UserName
|
||||
if (success && username) {
|
||||
success = false;
|
||||
_at.cmd_start("AT+UPSD=" PROFILE ",2,");
|
||||
_at.write_string(username);
|
||||
_at.cmd_stop_read_resp();
|
||||
|
||||
if (_at.get_last_error() == NSAPI_ERROR_OK) {
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
// Set up the Password
|
||||
if (success && password) {
|
||||
success = false;
|
||||
_at.cmd_start("AT+UPSD=" PROFILE ",3,");
|
||||
_at.write_string(password);
|
||||
_at.cmd_stop_read_resp();
|
||||
|
||||
if (_at.get_last_error() == NSAPI_ERROR_OK) {
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (success) {
|
||||
_at.cmd_start("AT+UPSD=" PROFILE ",7,\"0.0.0.0\"");
|
||||
_at.cmd_stop_read_resp();
|
||||
|
||||
// Set up the authentication protocol
|
||||
// 0 = none
|
||||
// 1 = PAP (Password Authentication Protocol)
|
||||
// 2 = CHAP (Challenge Handshake Authentication Protocol)
|
||||
for (int protocol = nsapi_security_to_modem_security(NSAPI_SECURITY_NONE);
|
||||
success && (protocol <= nsapi_security_to_modem_security(NSAPI_SECURITY_CHAP)); protocol++) {
|
||||
if ((_auth == NSAPI_SECURITY_UNKNOWN) || (nsapi_security_to_modem_security(_auth) == protocol)) {
|
||||
_at.cmd_start("AT+UPSD=0,6,");
|
||||
_at.write_int(protocol);
|
||||
_at.cmd_stop_read_resp();
|
||||
|
||||
if (_at.get_last_error() == NSAPI_ERROR_OK) {
|
||||
// Activate, wait upto 30 seconds for the connection to be made
|
||||
_at.set_at_timeout(30000);
|
||||
_at.cmd_start("AT+UPSDA=0,3");
|
||||
_at.cmd_stop_read_resp();
|
||||
_at.restore_at_timeout();
|
||||
|
||||
if (_at.get_last_error() == NSAPI_ERROR_OK) {
|
||||
activated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return activated;
|
||||
}
|
||||
|
||||
// Convert nsapi_security_t to the modem security numbers
|
||||
int UBLOX_AT_CellularNetwork::nsapi_security_to_modem_security(nsapi_security_t nsapi_security)
|
||||
{
|
||||
int modem_security = 3;
|
||||
|
||||
switch (nsapi_security) {
|
||||
case NSAPI_SECURITY_NONE:
|
||||
modem_security = 0;
|
||||
break;
|
||||
case NSAPI_SECURITY_PAP:
|
||||
modem_security = 1;
|
||||
break;
|
||||
case NSAPI_SECURITY_CHAP:
|
||||
modem_security = 2;
|
||||
break;
|
||||
case NSAPI_SECURITY_UNKNOWN:
|
||||
modem_security = 3;
|
||||
break;
|
||||
default:
|
||||
modem_security = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
return modem_security;
|
||||
}
|
||||
|
||||
// Disconnect the on board IP stack of the modem.
|
||||
bool UBLOX_AT_CellularNetwork::disconnect_modem_stack()
|
||||
{
|
||||
bool success = false;
|
||||
|
||||
if (get_ip_address() != NULL) {
|
||||
_at.cmd_start("AT+UPSDA=" PROFILE ",4");
|
||||
_at.cmd_stop_read_resp();
|
||||
|
||||
if (_at.get_last_error() == NSAPI_ERROR_OK) {
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
nsapi_error_t UBLOX_AT_CellularNetwork::get_imsi(char *imsi)
|
||||
{
|
||||
_at.lock();
|
||||
_at.cmd_start("AT+CIMI");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
int len = _at.read_string(imsi, MAX_IMSI_LENGTH);
|
||||
if (len > 0) {
|
||||
imsi[len] = '\0';
|
||||
}
|
||||
_at.resp_stop();
|
||||
|
||||
return _at.unlock_return_error();
|
||||
}
|
||||
|
||||
// Get the next set of credentials, based on IMSI.
|
||||
void UBLOX_AT_CellularNetwork::get_next_credentials(char **config)
|
||||
{
|
||||
if (*config) {
|
||||
_apn = _APN_GET(*config);
|
||||
_uname = _APN_GET(*config);
|
||||
_pwd = _APN_GET(*config);
|
||||
}
|
||||
}
|
||||
|
||||
const char *UBLOX_AT_CellularNetwork::get_gateway()
|
||||
{
|
||||
return get_ip_address();
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#define UBLOX_AT_CELLULAR_NETWORK_H_
|
||||
|
||||
#include "AT_CellularNetwork.h"
|
||||
#include "APN_db.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
|
@ -28,67 +27,9 @@ public:
|
|||
UBLOX_AT_CellularNetwork(ATHandler &atHandler);
|
||||
virtual ~UBLOX_AT_CellularNetwork();
|
||||
|
||||
virtual nsapi_error_t connect();
|
||||
|
||||
virtual const char *get_gateway();
|
||||
|
||||
protected:
|
||||
virtual NetworkStack *get_stack();
|
||||
|
||||
virtual nsapi_error_t set_access_technology_impl(RadioAccessTechnology opRat);
|
||||
|
||||
virtual bool get_modem_stack_type(nsapi_ip_stack_t requested_stack);
|
||||
|
||||
virtual RegistrationMode has_registration(RegistrationType rat);
|
||||
|
||||
private:
|
||||
|
||||
/** Length of IMSI buffer.
|
||||
*/
|
||||
static const int MAX_IMSI_LENGTH = 15;
|
||||
|
||||
/** The type of authentication to use.
|
||||
*/
|
||||
nsapi_security_t _auth;
|
||||
|
||||
/** Connect the on board IP stack of the modem.
|
||||
*
|
||||
* @return True if successful, otherwise false.
|
||||
*/
|
||||
nsapi_error_t open_data_channel();
|
||||
|
||||
/** Activate one of the on-board modem's connection profiles.
|
||||
*
|
||||
* @param apn The APN to use.
|
||||
* @param username The user name to use.
|
||||
* @param password The password to use.
|
||||
* @param auth The authentication method to use
|
||||
* (NSAPI_SECURITY_NONE, NSAPI_SECURITY_PAP,
|
||||
* NSAPI_SECURITY_CHAP or NSAPI_SECURITY_UNKNOWN).
|
||||
* @return True if successful, otherwise false.
|
||||
*/
|
||||
bool activate_profile(const char *apn, const char *username, const char *password);
|
||||
|
||||
/** Convert nsapi_security_t to the modem security numbers.
|
||||
*
|
||||
* @param nsapi_security Security protocol.
|
||||
* @return Modem security numbers.
|
||||
*/
|
||||
int nsapi_security_to_modem_security(nsapi_security_t nsapi_security);
|
||||
|
||||
/** Disconnect the on board IP stack of the modem.
|
||||
*
|
||||
* @return True if successful, otherwise false.
|
||||
*/
|
||||
bool disconnect_modem_stack();
|
||||
|
||||
/** Read IMSI of modem.
|
||||
*/
|
||||
nsapi_error_t get_imsi(char *imsi);
|
||||
|
||||
/** Get the next set of credentials from the database.
|
||||
*/
|
||||
void get_next_credentials(char **config);
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
|
|
@ -193,12 +193,9 @@ nsapi_size_or_error_t UBLOX_AT_CellularStack::socket_sendto_impl(CellularSocket
|
|||
const void *data, nsapi_size_t size)
|
||||
{
|
||||
int sent_len = 0;
|
||||
uint8_t ch = 0, cont = 50;
|
||||
|
||||
pollfh fhs;
|
||||
fhs.fh = _at.get_file_handle();
|
||||
fhs.events = POLLIN;
|
||||
int pollCount;
|
||||
|
||||
if (socket->proto == NSAPI_UDP) {
|
||||
if (size > UBLOX_MAX_PACKET_SIZE) {
|
||||
|
@ -210,7 +207,7 @@ nsapi_size_or_error_t UBLOX_AT_CellularStack::socket_sendto_impl(CellularSocket
|
|||
_at.write_int(address.get_port());
|
||||
_at.write_int(size);
|
||||
_at.cmd_stop();
|
||||
pollCount = poll(&fhs, 1, 50);
|
||||
(void)poll(&fhs, 1, 50);
|
||||
_at.write_bytes((uint8_t *)data, size);
|
||||
|
||||
_at.resp_start("+USOST:");
|
||||
|
@ -235,7 +232,7 @@ nsapi_size_or_error_t UBLOX_AT_CellularStack::socket_sendto_impl(CellularSocket
|
|||
_at.write_int(socket->id);
|
||||
_at.write_int(blk);
|
||||
_at.cmd_stop();
|
||||
pollCount = poll(&fhs, 1, 50);
|
||||
(void)poll(&fhs, 1, 50);
|
||||
_at.write_bytes((uint8_t *)buf, blk);
|
||||
|
||||
_at.resp_start("+USOWR:");
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "UBLOX_PPP.h"
|
||||
#include "UBLOX_PPP_CellularNetwork.h"
|
||||
#include "UBLOX_PPP_CellularPower.h"
|
||||
#include "UBLOX_PPP_CellularContext.h"
|
||||
|
||||
using namespace mbed;
|
||||
using namespace events;
|
||||
|
@ -49,3 +50,8 @@ AT_CellularPower *UBLOX_PPP::open_power_impl(ATHandler &at)
|
|||
{
|
||||
return new UBLOX_PPP_CellularPower(at);
|
||||
}
|
||||
|
||||
AT_CellularContext *UBLOX_PPP::create_context_impl(ATHandler &at, const char *apn, nsapi_ip_stack_t stack)
|
||||
{
|
||||
return new UBLOX_PPP_CellularContext(at, this, apn, stack);
|
||||
}
|
||||
|
|
|
@ -30,10 +30,7 @@ public:
|
|||
protected: // AT_CellularDevice
|
||||
virtual AT_CellularNetwork *open_network_impl(ATHandler &at);
|
||||
virtual AT_CellularPower *open_power_impl(ATHandler &at);
|
||||
};
|
||||
|
||||
MBED_DEPRECATED_SINCE("mbed-os-5.9", "This API will be deprecated, Use UBLOX_PPP instead of UBLOX_LISA_U.")
|
||||
class UBLOX_LISA_U : public UBLOX_PPP {
|
||||
virtual AT_CellularContext *create_context_impl(ATHandler &at, const char *apn, nsapi_ip_stack_t stack);
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* 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 "UBLOX_PPP_CellularContext.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
UBLOX_PPP_CellularContext::UBLOX_PPP_CellularContext(ATHandler &at, CellularDevice *device, const char *apn,
|
||||
nsapi_ip_stack_t stack) : AT_CellularContext(at, device, apn, stack)
|
||||
{
|
||||
}
|
||||
|
||||
UBLOX_PPP_CellularContext::~UBLOX_PPP_CellularContext()
|
||||
{
|
||||
}
|
||||
|
||||
bool UBLOX_PPP_CellularContext::stack_type_supported(nsapi_ip_stack_t requested_stack)
|
||||
{
|
||||
return requested_stack == IPV4_STACK ? true : false;
|
||||
}
|
||||
|
||||
} /* namespace mbed */
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef UBLOX_PPP_CELLULARCONTEXT_H_
|
||||
#define UBLOX_PPP_CELLULARCONTEXT_H_
|
||||
|
||||
#include "AT_CellularContext.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
class UBLOX_PPP_CellularContext: public AT_CellularContext {
|
||||
public:
|
||||
UBLOX_PPP_CellularContext(ATHandler &at, CellularDevice *device, const char *apn, nsapi_ip_stack_t stack);
|
||||
virtual ~UBLOX_PPP_CellularContext();
|
||||
|
||||
protected:
|
||||
virtual bool stack_type_supported(nsapi_ip_stack_t requested_stack);
|
||||
};
|
||||
|
||||
} /* namespace mbed */
|
||||
|
||||
#endif // UBLOX_PPP_CELLULARCONTEXT_H_
|
|
@ -27,11 +27,6 @@ UBLOX_PPP_CellularNetwork::~UBLOX_PPP_CellularNetwork()
|
|||
{
|
||||
}
|
||||
|
||||
bool UBLOX_PPP_CellularNetwork::get_modem_stack_type(nsapi_ip_stack_t requested_stack)
|
||||
{
|
||||
return requested_stack == IPV4_STACK ? true : false;
|
||||
}
|
||||
|
||||
AT_CellularNetwork::RegistrationMode UBLOX_PPP_CellularNetwork::has_registration(RegistrationType reg_type)
|
||||
{
|
||||
return (reg_type == C_REG || reg_type == C_GREG) ? RegistrationModeLAC : RegistrationModeDisable;
|
||||
|
|
|
@ -28,17 +28,10 @@ public:
|
|||
virtual ~UBLOX_PPP_CellularNetwork();
|
||||
|
||||
protected:
|
||||
virtual bool get_modem_stack_type(nsapi_ip_stack_t requested_stack);
|
||||
|
||||
virtual RegistrationMode has_registration(RegistrationType rat);
|
||||
|
||||
virtual nsapi_error_t set_access_technology_impl(RadioAccessTechnology opRat);
|
||||
};
|
||||
|
||||
MBED_DEPRECATED_SINCE("mbed-os-5.9", "This API will be deprecated, Use UBLOX_PPP_CellularNetwork instead of UBLOX_LISA_U_CellularNetwork.")
|
||||
class UBLOX_LISA_U_CellularNetwork : public UBLOX_PPP_CellularNetwork {
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
||||
#endif // UBLOX_PPP_CELLULAR_NETWORK_H_
|
||||
|
|
|
@ -34,10 +34,6 @@ public: //from CellularPower
|
|||
virtual nsapi_error_t off();
|
||||
};
|
||||
|
||||
MBED_DEPRECATED_SINCE("mbed-os-5.9", "This API will be deprecated, Use UBLOX_PPP_CellularPower instead of UBLOX_LISA_U_CellularPower.")
|
||||
class UBLOX_LISA_U_CellularPower : public UBLOX_PPP_CellularPower {
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
||||
#endif // UBLOX_PPP_CELLULARPOWER_H_
|
||||
|
|
|
@ -110,27 +110,8 @@ MBED_WEAK NetworkInterface *NetworkInterface::get_target_default_instance()
|
|||
#elif MBED_CONF_TARGET_NETWORK_DEFAULT_INTERFACE_TYPE == CELLULAR
|
||||
MBED_WEAK NetworkInterface *NetworkInterface::get_target_default_instance()
|
||||
{
|
||||
CellularBase *cellular = CellularBase::get_default_instance();
|
||||
if (!cellular) {
|
||||
return NULL;
|
||||
}
|
||||
/* CellularBase is expected to attempt to work without any parameters - we
|
||||
* will try, at least.
|
||||
*/
|
||||
#ifdef MBED_CONF_NSAPI_DEFAULT_CELLULAR_APN
|
||||
#ifndef MBED_CONF_NSAPI_DEFAULT_CELLULAR_USERNAME
|
||||
#define MBED_CONF_NSAPI_DEFAULT_CELLULAR_USERNAME NULL
|
||||
#endif
|
||||
#ifndef MBED_CONF_NSAPI_DEFAULT_CELLULAR_PASSWORD
|
||||
#define MBED_CONF_NSAPI_DEFAULT_CELLULAR_PASSWORD NULL
|
||||
#endif
|
||||
cellular->set_credentials(MBED_CONF_NSAPI_DEFAULT_CELLULAR_APN, MBED_CONF_NSAPI_DEFAULT_CELLULAR_USERNAME, MBED_CONF_NSAPI_DEFAULT_CELLULAR_PASSWORD);
|
||||
#endif
|
||||
#ifdef MBED_CONF_NSAPI_DEFAULT_CELLULAR_SIM_PIN
|
||||
cellular->set_sim_pin(MBED_CONF_NSAPI_DEFAULT_CELLULAR_SIM_PIN);
|
||||
#endif
|
||||
return CellularContext::get_default_instance();
|
||||
|
||||
return cellular;
|
||||
}
|
||||
#elif defined(MBED_CONF_TARGET_NETWORK_DEFAULT_INTERFACE_TYPE)
|
||||
/* If anyone invents a new JSON value, they must have their own default weak
|
||||
|
|
|
@ -6,10 +6,11 @@
|
|||
"default-wifi-ssid": null,
|
||||
"default-wifi-password": null,
|
||||
"default-wifi-security": "NONE",
|
||||
"default-cellular-sim-pin": null,
|
||||
"default-cellular-apn": null,
|
||||
"default-cellular-username": null,
|
||||
"default-cellular-password": null,
|
||||
"default-cellular-plmn": 0,
|
||||
"default-cellular-sim-pin": 0,
|
||||
"default-cellular-apn": 0,
|
||||
"default-cellular-username": 0,
|
||||
"default-cellular-password": 0,
|
||||
"default-mesh-type": {
|
||||
"help": "Configuration type for MeshInterface::get_default_instance(). [LOWPAN/THREAD]",
|
||||
"value": "THREAD"
|
||||
|
|
|
@ -69,7 +69,6 @@ typedef enum nsapi_connection_status {
|
|||
NSAPI_STATUS_GLOBAL_UP = 1, /*!< global IP address set */
|
||||
NSAPI_STATUS_DISCONNECTED = 2, /*!< no connection to network */
|
||||
NSAPI_STATUS_CONNECTING = 3, /*!< connecting to network */
|
||||
NSAPI_STATUS_RECONNECTING = 4, /*!< reconnecting to network */
|
||||
NSAPI_STATUS_ERROR_UNSUPPORTED = NSAPI_ERROR_UNSUPPORTED
|
||||
} nsapi_connection_status_t;
|
||||
|
||||
|
|
Loading…
Reference in New Issue