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