mirror of https://github.com/ARMmbed/mbed-os.git
371 lines
10 KiB
C++
371 lines
10 KiB
C++
/*
|
|
* 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"
|
|
#include "CellularLog.h"
|
|
#include "rtos/ThisThread.h"
|
|
|
|
using namespace std::chrono_literals;
|
|
|
|
namespace mbed {
|
|
|
|
UBLOX_AT_CellularContext::UBLOX_AT_CellularContext(ATHandler &at, CellularDevice *device, const char *apn, bool cp_req, bool nonip_req) :
|
|
AT_CellularContext(at, device, apn, cp_req, nonip_req)
|
|
{
|
|
// The authentication to use
|
|
_auth = NOAUTH;
|
|
}
|
|
|
|
UBLOX_AT_CellularContext::~UBLOX_AT_CellularContext()
|
|
{
|
|
}
|
|
|
|
NetworkStack *UBLOX_AT_CellularContext::get_stack()
|
|
{
|
|
if (_pdp_type == NON_IP_PDP_TYPE || _cp_in_use) {
|
|
tr_error("Requesting stack for NON-IP context! Should request control plane netif: get_cp_netif()");
|
|
return NULL;
|
|
}
|
|
if (!_stack) {
|
|
_stack = new UBLOX_AT_CellularStack(_at, _cid, (nsapi_ip_stack_t)_pdp_type, *get_device());
|
|
}
|
|
|
|
return _stack;
|
|
}
|
|
|
|
void UBLOX_AT_CellularContext::do_connect()
|
|
{
|
|
_at.lock();
|
|
_cb_data.error = NSAPI_ERROR_NO_CONNECTION;
|
|
|
|
// Attempt to establish a connection
|
|
#ifndef UBX_MDM_SARA_R41XM
|
|
_cb_data.error = define_context();
|
|
#elif UBX_MDM_SARA_R410M
|
|
_at.cmd_start_stop("+CGACT", "?");
|
|
_at.resp_start("+CGACT:");
|
|
_cid = _at.read_int();
|
|
_at.skip_param(1);
|
|
_at.resp_stop();
|
|
|
|
_is_connected = true;
|
|
_is_context_active = true;
|
|
_is_context_activated = true;
|
|
_cb_data.error = NSAPI_ERROR_OK;
|
|
#elif UBX_MDM_SARA_R412M
|
|
CellularNetwork::RadioAccessTechnology rat = read_radio_technology();
|
|
if (rat == CellularNetwork::RadioAccessTechnology::RAT_EGPRS) {
|
|
if (!_is_context_active) {
|
|
_at.set_at_timeout(150s);
|
|
_at.at_cmd_discard("+CGACT", "=", "%d%d", 1, 1);
|
|
|
|
_at.cmd_start_stop("+CGACT", "?");
|
|
_at.resp_start("+CGACT:");
|
|
_at.skip_param(1);
|
|
_is_context_activated = _at.read_int();
|
|
_at.resp_stop();
|
|
_at.restore_at_timeout();
|
|
if (_is_context_activated == true) {
|
|
_cid = 1;
|
|
_is_connected = true;
|
|
_is_context_active = true;
|
|
_cb_data.error = NSAPI_ERROR_OK;
|
|
}
|
|
}
|
|
} else if (rat == CellularNetwork::RadioAccessTechnology::RAT_CATM1 || rat == CellularNetwork::RadioAccessTechnology::RAT_NB1) {
|
|
_at.cmd_start_stop("+CGACT", "?");
|
|
_at.resp_start("+CGACT:");
|
|
_cid = _at.read_int();
|
|
_at.skip_param(1);
|
|
_at.resp_stop();
|
|
|
|
_is_connected = true;
|
|
_is_context_active = true;
|
|
_is_context_activated = true;
|
|
_cb_data.error = NSAPI_ERROR_OK;
|
|
}
|
|
#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) {
|
|
_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, _connect_status);
|
|
}
|
|
}
|
|
#ifndef UBX_MDM_SARA_R41XM
|
|
void UBLOX_AT_CellularContext::do_disconnect()
|
|
{
|
|
disconnect_modem_stack();
|
|
AT_CellularContext::do_disconnect();
|
|
}
|
|
#endif
|
|
|
|
#ifndef UBX_MDM_SARA_R41XM
|
|
nsapi_error_t UBLOX_AT_CellularContext::define_context()
|
|
{
|
|
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.lock();
|
|
_at.cmd_start_stop("+UPSND", "=", "%d%d", PROFILE, 8);
|
|
_at.resp_start("+UPSND:");
|
|
_at.skip_param(2);
|
|
active = _at.read_int();
|
|
_at.resp_stop();
|
|
_at.unlock();
|
|
|
|
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) ? _authentication_type : NOAUTH;
|
|
} else {
|
|
_auth = NOAUTH;
|
|
}
|
|
success = activate_profile(_apn, _uname, _pwd, _auth);
|
|
} 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,
|
|
AuthenticationType auth)
|
|
{
|
|
bool activated = false;
|
|
bool success = false;
|
|
|
|
// Set up the APN
|
|
if (apn) {
|
|
success = false;
|
|
if (_at.at_cmd_discard("+UPSD", "=", "%d%d%s", PROFILE, 1, apn) == NSAPI_ERROR_OK) {
|
|
success = true;
|
|
}
|
|
}
|
|
// Set up the UserName
|
|
if (success && username) {
|
|
success = false;
|
|
if (_at.at_cmd_discard("+UPSD", "=", "%d%d%s", PROFILE, 2, username) == NSAPI_ERROR_OK) {
|
|
success = true;
|
|
}
|
|
}
|
|
// Set up the Password
|
|
if (success && password) {
|
|
success = false;
|
|
if (_at.at_cmd_discard("+UPSD", "=", "%d%d%s", PROFILE, 3, password) == NSAPI_ERROR_OK) {
|
|
success = true;
|
|
}
|
|
}
|
|
|
|
if (success) {
|
|
_at.at_cmd_discard("+UPSD", "=", "%d%d%s", PROFILE, 7, "0.0.0.0");
|
|
|
|
if (_at.at_cmd_discard("+UPSD", "=", "%d%d%d", PROFILE, 6, nsapi_security_to_modem_security(auth)) == NSAPI_ERROR_OK) {
|
|
// Activate, wait upto 30 seconds for the connection to be made
|
|
_at.set_at_timeout(30s);
|
|
|
|
nsapi_error_t err = _at.at_cmd_discard("+UPSDA", "=", "%d%d", PROFILE, 3);
|
|
|
|
_at.restore_at_timeout();
|
|
|
|
if (err == NSAPI_ERROR_OK) {
|
|
auto end_time = rtos::Kernel::Clock::now() + 3min;
|
|
do {
|
|
_at.lock();
|
|
_at.cmd_start_stop("+UPSND", "=", "%d%d", PROFILE, 8);
|
|
_at.resp_start("+UPSND:");
|
|
_at.skip_param(2);
|
|
_at.read_int() ? activated = true : activated = false;
|
|
_at.resp_stop();
|
|
_at.unlock();
|
|
|
|
if (activated) { //If context is activated, exit while loop and return status
|
|
break;
|
|
}
|
|
rtos::ThisThread::sleep_for(5s); //Wait for 5 seconds and then try again
|
|
} while (rtos::Kernel::Clock::now() < end_time);
|
|
}
|
|
}
|
|
}
|
|
|
|
return activated;
|
|
}
|
|
#endif
|
|
|
|
// Convert nsapi_security_t to the modem security numbers
|
|
int UBLOX_AT_CellularContext::nsapi_security_to_modem_security(AuthenticationType nsapi_security)
|
|
{
|
|
int modem_security = 3;
|
|
|
|
switch (nsapi_security) {
|
|
case NOAUTH:
|
|
modem_security = 0;
|
|
break;
|
|
case PAP:
|
|
modem_security = 1;
|
|
break;
|
|
case CHAP:
|
|
modem_security = 2;
|
|
break;
|
|
#ifndef UBX_MDM_SARA_R41XM
|
|
case AUTOMATIC:
|
|
modem_security = 3;
|
|
break;
|
|
default:
|
|
modem_security = 3;
|
|
break;
|
|
#else
|
|
default:
|
|
modem_security = 0;
|
|
break;
|
|
#endif
|
|
}
|
|
|
|
return modem_security;
|
|
}
|
|
|
|
// Disconnect the on board IP stack of the modem.
|
|
bool UBLOX_AT_CellularContext::disconnect_modem_stack()
|
|
{
|
|
SocketAddress addr;
|
|
if (get_ip_address(&addr) == NSAPI_ERROR_OK) {
|
|
if (_at.at_cmd_discard("+UPSDA", "=", "%d%d", PROFILE, 4) == NSAPI_ERROR_OK) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
nsapi_error_t UBLOX_AT_CellularContext::get_imsi(char *imsi)
|
|
{
|
|
_at.lock();
|
|
_at.cmd_start_stop("+CIMI", "");
|
|
_at.resp_start();
|
|
_at.read_string(imsi, MAX_IMSI_LENGTH + 1);
|
|
_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);
|
|
}
|
|
}
|
|
|
|
nsapi_error_t UBLOX_AT_CellularContext::get_gateway(SocketAddress *addr)
|
|
{
|
|
return get_ip_address(addr);
|
|
}
|
|
|
|
const char *UBLOX_AT_CellularContext::get_apn()
|
|
{
|
|
return _apn;
|
|
}
|
|
|
|
const char *UBLOX_AT_CellularContext::get_uname()
|
|
{
|
|
return _uname;
|
|
}
|
|
|
|
const char *UBLOX_AT_CellularContext::get_pwd()
|
|
{
|
|
return _pwd;
|
|
}
|
|
|
|
CellularContext::AuthenticationType UBLOX_AT_CellularContext::get_auth()
|
|
{
|
|
return _authentication_type;
|
|
}
|
|
|
|
#ifdef UBX_MDM_SARA_R412M
|
|
CellularNetwork::RadioAccessTechnology UBLOX_AT_CellularContext::read_radio_technology()
|
|
{
|
|
int act;
|
|
CellularNetwork::RadioAccessTechnology rat;
|
|
|
|
_at.at_cmd_int("+URAT", "?", act);
|
|
|
|
switch (act) {
|
|
case 0:
|
|
rat = CellularNetwork::RadioAccessTechnology::RAT_GSM;
|
|
break;
|
|
case 1:
|
|
rat = CellularNetwork::RadioAccessTechnology::RAT_GSM;
|
|
break;
|
|
case 2:
|
|
rat = CellularNetwork::RadioAccessTechnology::RAT_UTRAN;
|
|
break;
|
|
case 7:
|
|
rat = CellularNetwork::RadioAccessTechnology::RAT_CATM1;
|
|
break;
|
|
case 8:
|
|
rat = CellularNetwork::RadioAccessTechnology::RAT_NB1;
|
|
break;
|
|
case 9:
|
|
rat = CellularNetwork::RadioAccessTechnology::RAT_EGPRS;
|
|
break;
|
|
default:
|
|
rat = CellularNetwork::RadioAccessTechnology::RAT_UNKNOWN;
|
|
break;
|
|
}
|
|
|
|
return rat;
|
|
}
|
|
#endif // #ifdef UBX_MDM_SARA_R412M
|
|
|
|
} /* namespace mbed */
|