Import Mbed OS hard-float snapshot

This commit is contained in:
Beslan
2026-06-01 20:15:04 +03:00
commit d3738e2f89
16278 changed files with 10628036 additions and 0 deletions

View File

@@ -0,0 +1,219 @@
/*
* 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.h"
using namespace mbed;
using namespace events;
#ifdef UBX_MDM_SARA_R41XM
static const intptr_t cellular_properties[AT_CellularDevice::PROPERTY_MAX] = {
AT_CellularNetwork::RegistrationModeDisable,// C_EREG
AT_CellularNetwork::RegistrationModeLAC, // C_GREG
AT_CellularNetwork::RegistrationModeLAC, // C_REG
0, // AT_CGSN_WITH_TYPE
0, // AT_CGDATA
0, // AT_CGAUTH
1, // AT_CNMI
1, // AT_CSMP
1, // AT_CMGF
0, // AT_CSDH
1, // PROPERTY_IPV4_STACK
0, // PROPERTY_IPV6_STACK
0, // PROPERTY_IPV4V6_STACK
0, // PROPERTY_NON_IP_PDP_TYPE
1, // PROPERTY_AT_CGEREP
1, // PROPERTY_AT_COPS_FALLBACK_AUTO
7, // PROPERTY_SOCKET_COUNT
1, // PROPERTY_IP_TCP
1, // PROPERTY_IP_UDP
0, // PROPERTY_AT_SEND_DELAY
};
#elif defined(UBX_MDM_SARA_U2XX) || defined(UBX_MDM_SARA_G3XX)
static const intptr_t cellular_properties[AT_CellularDevice::PROPERTY_MAX] = {
AT_CellularNetwork::RegistrationModeDisable,// C_EREG
AT_CellularNetwork::RegistrationModeLAC, // C_GREG
AT_CellularNetwork::RegistrationModeLAC, // C_REG
#ifdef UBX_MDM_SARA_G3XX
0, // AT_CGSN_WITH_TYPE
#else
1, // AT_CGSN_WITH_TYPE
#endif
1, // AT_CGDATA
0, // AT_CGAUTH
1, // AT_CNMI
1, // AT_CSMP
1, // AT_CMGF
1, // AT_CSDH
1, // PROPERTY_IPV4_STACK
0, // PROPERTY_IPV6_STACK
0, // PROPERTY_IPV4V6_STACK
0, // PROPERTY_NON_IP_PDP_TYPE
1, // PROPERTY_AT_CGEREP
1, // PROPERTY_AT_COPS_FALLBACK_AUTO
7, // PROPERTY_SOCKET_COUNT
1, // PROPERTY_IP_TCP
1, // PROPERTY_IP_UDP
0, // PROPERTY_AT_SEND_DELAY
};
#else
static const intptr_t cellular_properties[AT_CellularDevice::PROPERTY_MAX] = {
0, // C_EREG
0, // C_GREG
0, // C_REG
0, // AT_CGSN_WITH_TYPE
0, // AT_CGDATA
0, // AT_CGAUTH
0, // AT_CNMI
0, // AT_CSMP
0, // AT_CMGF
0, // AT_CSDH
0, // PROPERTY_IPV4_STACK
0, // PROPERTY_IPV6_STACK
0, // PROPERTY_IPV4V6_STACK
0, // PROPERTY_NON_IP_PDP_TYPE
0, // PROPERTY_AT_CGEREP
0, // PROPERTY_AT_COPS_FALLBACK_AUTO
0, // PROPERTY_SOCKET_COUNT
0, // PROPERTY_IP_TCP
0, // PROPERTY_IP_UDP
0, // PROPERTY_AT_SEND_DELAY
};
#endif
UBLOX_AT::UBLOX_AT(FileHandle *fh) : AT_CellularDevice(fh), ubx_context(0)
{
set_cellular_properties(cellular_properties);
}
AT_CellularNetwork *UBLOX_AT::open_network_impl(ATHandler &at)
{
return new UBLOX_AT_CellularNetwork(at, *this);
}
AT_CellularContext *UBLOX_AT::create_context_impl(ATHandler &at, const char *apn, bool cp_req, bool nonip_req)
{
ubx_context = new UBLOX_AT_CellularContext(at, this, apn, cp_req, nonip_req);
return ubx_context;
}
#if MBED_CONF_UBLOX_AT_PROVIDE_DEFAULT
#include "drivers/BufferedSerial.h"
CellularDevice *CellularDevice::get_default_instance()
{
static BufferedSerial serial(MBED_CONF_UBLOX_AT_TX, MBED_CONF_UBLOX_AT_RX, MBED_CONF_UBLOX_AT_BAUDRATE);
#if defined (MBED_CONF_UBLOX_AT_RTS) && defined(MBED_CONF_UBLOX_AT_CTS)
tr_debug("UBLOX_AT flow control: RTS %d CTS %d", MBED_CONF_UBLOX_AT_RTS, MBED_CONF_UBLOX_AT_CTS);
serial.set_flow_control(SerialBase::RTSCTS, MBED_CONF_UBLOX_AT_RTS, MBED_CONF_UBLOX_AT_CTS);
#endif
static UBLOX_AT device(&serial);
return &device;
}
#endif
nsapi_error_t UBLOX_AT::init()
{
setup_at_handler();
_at.lock();
_at.flush();
_at.at_cmd_discard("", "");
#if defined(UBX_MDM_SARA_U2XX) || defined(UBX_MDM_SARA_G3XX)
nsapi_error_t err = _at.at_cmd_discard("E0", ""); // echo off
if (err == NSAPI_ERROR_OK) {
_at.at_cmd_discard("+CMEE", "=1"); // verbose responses
err = _at.at_cmd_discard("+CFUN", "=1"); // set full functionality
}
#elif defined(UBX_MDM_SARA_R41XM)
nsapi_error_t err = _at.at_cmd_discard("+CFUN", "=", "%d", 4);
if (err == NSAPI_ERROR_OK) {
_at.at_cmd_discard("E0", ""); // echo off
_at.at_cmd_discard("+CMEE", "=1"); // verbose responses
config_authentication_parameters();
err = _at.at_cmd_discard("+CFUN", "=1"); // set full functionality
}
#else
_at.unlock();
return NSAPI_ERROR_UNSUPPORTED;
#endif
return _at.unlock_return_error();
}
nsapi_error_t UBLOX_AT::config_authentication_parameters()
{
char *config = NULL;
nsapi_error_t err;
const char *apn;
const char *uname;
const char *pwd;
CellularContext::AuthenticationType auth = CellularContext::NOAUTH;
char imsi[MAX_IMSI_LENGTH + 1];
if (ubx_context->get_apn() == NULL) {
err = get_imsi(imsi);
if (err == NSAPI_ERROR_OK) {
config = (char *)apnconfig(imsi);
}
ubx_context->get_next_credentials(&config);
}
apn = ubx_context->get_apn();
pwd = ubx_context->get_pwd();
uname = ubx_context->get_uname();
if (*uname && *pwd) {
auth = ubx_context->get_auth();
}
err = set_authentication_parameters(apn, uname, pwd, auth);
return err;
}
nsapi_error_t UBLOX_AT::set_authentication_parameters(const char *apn,
const char *username,
const char *password,
CellularContext::AuthenticationType auth)
{
int modem_security = ubx_context->nsapi_security_to_modem_security(auth);
nsapi_error_t err = _at.at_cmd_discard("+CGDCONT", "=", "%d%s%s", 1, "IP", apn);
if (err == NSAPI_ERROR_OK) {
#ifdef UBX_MDM_SARA_R41XM
if (modem_security == CellularContext::CHAP) {
err = _at.at_cmd_discard("+UAUTHREQ", "=", "%d%d%s%s", 1, modem_security, password, username);
} else if (modem_security == CellularContext::NOAUTH) {
err = _at.at_cmd_discard("+UAUTHREQ", "=", "%d%d", 1, modem_security);
} else {
err = _at.at_cmd_discard("+UAUTHREQ", "=", "%d%d%s%s", 1, modem_security, username, password);
}
#else
err = _at.at_cmd_discard("+UAUTHREQ", "=", "%d%d%s%s", 1, modem_security, username, password);
#endif
}
return err;
}
nsapi_error_t UBLOX_AT::get_imsi(char *imsi)
{
//Special case: Command put in cmd_chr to make a 1 liner
return _at.at_cmd_str("", "+CIMI", imsi, MAX_IMSI_LENGTH + 1);
}

View File

@@ -0,0 +1,69 @@
/*
* 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_H_
#define UBLOX_AT_H_
#ifdef TARGET_FF_ARDUINO
#ifndef MBED_CONF_UBLOX_AT_TX
#define MBED_CONF_UBLOX_AT_TX D1
#endif
#ifndef MBED_CONF_UBLOX_AT_RX
#define MBED_CONF_UBLOX_AT_RX D0
#endif
#endif /* TARGET_FF_ARDUINO */
#include "APN_db.h"
#include "AT_CellularDevice.h"
#include "AT_CellularContext.h"
#include "UBLOX_AT_CellularNetwork.h"
#include "UBLOX_AT_CellularContext.h"
namespace mbed {
class UBLOX_AT : public AT_CellularDevice {
public:
UBLOX_AT(FileHandle *fh);
protected: // AT_CellularDevice
virtual AT_CellularNetwork *open_network_impl(ATHandler &at);
virtual AT_CellularContext *create_context_impl(ATHandler &at, const char *apn, bool cp_req = false, bool nonip_req = false);
public: // NetworkInterface
void handle_urc(FileHandle *fh);
virtual nsapi_error_t init();
private:
UBLOX_AT_CellularContext *ubx_context;
/** Length of IMSI buffer.
*/
static const int MAX_IMSI_LENGTH = 15;
nsapi_error_t config_authentication_parameters();
nsapi_error_t set_authentication_parameters(const char *apn, const char *username, const char *password, CellularContext::AuthenticationType auth);
/** Read IMSI of modem.
*/
nsapi_error_t get_imsi(char *imsi);
};
} // namespace mbed
#endif // UBLOX_AT_H_

View File

@@ -0,0 +1,370 @@
/*
* 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 */

View File

@@ -0,0 +1,102 @@
/*
* 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"
#include "UBLOX_AT_CellularNetwork.h"
namespace mbed {
class UBLOX_AT_CellularContext: public AT_CellularContext {
public:
UBLOX_AT_CellularContext(ATHandler &at, CellularDevice *device, const char *apn, bool cp_req = false, bool nonip_req = false);
virtual ~UBLOX_AT_CellularContext();
virtual void do_connect();
#ifndef UBX_MDM_SARA_R41XM
virtual void do_disconnect();
#endif
virtual nsapi_error_t get_gateway(SocketAddress *addr);
const char *get_apn(void);
const char *get_uname(void);
const char *get_pwd(void);
CellularContext::AuthenticationType get_auth(void);
/** Convert nsapi_security_t to the modem security numbers.
*
* @param nsapi_security Security protocol.
* @return Modem security numbers.
*/
int nsapi_security_to_modem_security(AuthenticationType nsapi_security);
/** Get the next set of credentials from the database.
*/
void get_next_credentials(char **config);
#ifdef UBX_MDM_SARA_R412M
CellularNetwork::RadioAccessTechnology read_radio_technology(void);
#endif
protected:
virtual NetworkStack *get_stack();
/** Connect the on board IP stack of the modem.
*
* @return True if successful, otherwise false.
*/
#ifndef UBX_MDM_SARA_R41XM
nsapi_error_t define_context();
#endif
private:
/** Length of IMSI buffer.
*/
static const int MAX_IMSI_LENGTH = 15;
/** The type of authentication to use.
*/
AuthenticationType _auth;
/** 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
* (NOAUTH, PAP,
* CHAP or AUTOMATIC).
* @return True if successful, otherwise false.
*/
#ifndef UBX_MDM_SARA_R41XM
bool activate_profile(const char *apn, const char *username, const char *password, AuthenticationType auth);
#endif
/** 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);
};
} /* namespace mbed */
#endif // UBLOX_AT_CELLULARCONTEXT_H_

View File

@@ -0,0 +1,104 @@
/*
* 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_CellularNetwork.h"
#include "rtos/ThisThread.h"
using namespace std::chrono_literals;
using namespace mbed;
UBLOX_AT_CellularNetwork::UBLOX_AT_CellularNetwork(ATHandler &atHandler, AT_CellularDevice &device) : AT_CellularNetwork(atHandler, device)
{
_op_act = RAT_UNKNOWN;
}
UBLOX_AT_CellularNetwork::~UBLOX_AT_CellularNetwork()
{
if (_connection_status_cb) {
_connection_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_ERROR_CONNECTION_LOST);
}
}
nsapi_error_t UBLOX_AT_CellularNetwork::set_access_technology_impl(RadioAccessTechnology opRat)
{
nsapi_error_t ret = NSAPI_ERROR_OK;
CellularNetwork::AttachStatus status;
get_attach(status);
if (status == Attached) {
tr_debug("RAT should only be set in detached state");
return NSAPI_ERROR_UNSUPPORTED;
}
_at.lock();
switch (opRat) {
case RAT_EGPRS:
#if defined (UBX_MDM_SARA_R412M)
_at.at_cmd_discard("+URAT", "=", "%d%d", 9, 8);
break;
#endif
#if defined(UBX_MDM_SARA_U201)
case RAT_GSM:
_at.at_cmd_discard("+URAT", "=", "%d%d", 0, 0);
break;
case RAT_UTRAN:
case RAT_HSDPA:
case RAT_HSUPA:
case RAT_HSDPA_HSUPA:
_at.at_cmd_discard("+URAT", "=", "%d%d", 2, 2);
break;
#elif defined(UBX_MDM_SARA_R41XM)
case RAT_CATM1:
_at.at_cmd_discard("+URAT", "=", "%d%d", 7, 8);
break;
case RAT_NB1:
_at.at_cmd_discard("+URAT", "=", "%d%d", 8, 7);
break;
#endif
default:
_op_act = RAT_UNKNOWN;
ret = NSAPI_ERROR_UNSUPPORTED;
break;
}
_at.unlock();
ubx_reboot();
return (ret);
}
nsapi_error_t UBLOX_AT_CellularNetwork::ubx_reboot()
{
_at.lock();
_at.at_cmd_discard("+CFUN", "=15");
nsapi_error_t err = NSAPI_ERROR_OK;
Timer t1;
t1.start();
while (!(t1.elapsed_time() >= 30s)) {
err = _at.at_cmd_discard("E0", "");
if (err == NSAPI_ERROR_OK) {
break;
} else {
//Don't clear err here so that we get some error in case of failure
_at.clear_error();
rtos::ThisThread::sleep_for(1s);
}
}
t1.stop();
_at.unlock();
return err;
}

View File

@@ -0,0 +1,42 @@
/*
* 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_CELLULAR_NETWORK_H_
#define UBLOX_AT_CELLULAR_NETWORK_H_
#include "CellularLog.h"
#include "drivers/Timer.h"
#include "mbed_wait_api.h"
#include "AT_CellularNetwork.h"
#include "AT_CellularContext.h"
namespace mbed {
class UBLOX_AT_CellularNetwork : public AT_CellularNetwork {
public:
UBLOX_AT_CellularNetwork(ATHandler &atHandler, AT_CellularDevice &device);
virtual ~UBLOX_AT_CellularNetwork();
nsapi_error_t ubx_reboot();
protected:
virtual nsapi_error_t set_access_technology_impl(RadioAccessTechnology opRat);
};
} // namespace mbed
#endif // UBLOX_AT_CELLULAR_NETWORK_H_

View File

@@ -0,0 +1,479 @@
/*
* 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_CellularStack.h"
#include "rtos/ThisThread.h"
using namespace mbed;
using namespace mbed_cellular_util;
using namespace std::chrono_literals;
UBLOX_AT_CellularStack::UBLOX_AT_CellularStack(ATHandler &atHandler, int cid, nsapi_ip_stack_t stack_type, AT_CellularDevice &device) :
AT_CellularStack(atHandler, cid, stack_type, device)
{
// URC handlers for sockets
_at.set_urc_handler("+UUSORD:", callback(this, &UBLOX_AT_CellularStack::UUSORD_URC));
_at.set_urc_handler("+UUSORF:", callback(this, &UBLOX_AT_CellularStack::UUSORF_URC));
_at.set_urc_handler("+UUSOCL:", callback(this, &UBLOX_AT_CellularStack::UUSOCL_URC));
_at.set_urc_handler("+UUPSDD:", callback(this, &UBLOX_AT_CellularStack::UUPSDD_URC));
}
UBLOX_AT_CellularStack::~UBLOX_AT_CellularStack()
{
}
nsapi_error_t UBLOX_AT_CellularStack::socket_listen(nsapi_socket_t handle, int backlog)
{
return NSAPI_ERROR_UNSUPPORTED;
}
nsapi_error_t UBLOX_AT_CellularStack::socket_accept(void *server, void **socket, SocketAddress *addr)
{
return NSAPI_ERROR_UNSUPPORTED;
}
// Callback for Socket Read URC.
void UBLOX_AT_CellularStack::UUSORD_URC()
{
int a, b;
CellularSocket *socket;
a = _at.read_int();
b = _at.read_int();
socket = find_socket(a);
if (socket != NULL) {
socket->pending_bytes = b;
// No debug prints here as they can affect timing
// and cause data loss in BufferedSerial
if (socket->_cb != NULL) {
socket->_cb(socket->_data);
}
}
}
// Callback for Socket Read From URC.
void UBLOX_AT_CellularStack::UUSORF_URC()
{
int a, b;
CellularSocket *socket;
a = _at.read_int();
b = _at.read_int();
socket = find_socket(a);
if (socket != NULL) {
socket->pending_bytes = b;
// No debug prints here as they can affect timing
// and cause data loss in BufferedSerial
if (socket->_cb != NULL) {
socket->_cb(socket->_data);
}
}
}
// Callback for Socket Close URC.
void UBLOX_AT_CellularStack::UUSOCL_URC()
{
int a;
CellularSocket *socket;
a = _at.read_int();
socket = find_socket(a);
clear_socket(socket);
}
// Callback for UUPSDD.
void UBLOX_AT_CellularStack::UUPSDD_URC()
{
int a;
CellularSocket *socket;
a = _at.read_int();
socket = find_socket(a);
clear_socket(socket);
}
nsapi_error_t UBLOX_AT_CellularStack::create_socket_impl(CellularSocket *socket)
{
int sock_id = SOCKET_UNUSED;
nsapi_error_t err = NSAPI_ERROR_OK;
if (socket->proto == NSAPI_UDP) {
err = _at.at_cmd_int("+USOCR", "=17", sock_id);
} else if (socket->proto == NSAPI_TCP) {
err = _at.at_cmd_int("+USOCR", "=6", sock_id);
} // Unsupported protocol is checked in socket_open()
if ((err != NSAPI_ERROR_OK) || (sock_id == -1)) {
return NSAPI_ERROR_NO_SOCKET;
}
// Check for duplicate socket id delivered by modem
for (int i = 0; i < _device.get_property(AT_CellularDevice::PROPERTY_SOCKET_COUNT); i++) {
CellularSocket *sock = _socket[i];
if (sock && sock != socket && sock->id == sock_id) {
return NSAPI_ERROR_NO_SOCKET;
}
}
socket->started = true;
socket->id = sock_id;
return err;
}
nsapi_error_t UBLOX_AT_CellularStack::socket_connect(nsapi_socket_t handle, const SocketAddress &addr)
{
CellularSocket *socket = (CellularSocket *)handle;
if (socket) {
if (socket->id == SOCKET_UNUSED) {
nsapi_error_t err = create_socket_impl(socket);
if (err != NSAPI_ERROR_OK) {
return err;
}
}
} else {
return NSAPI_ERROR_DEVICE_ERROR;
}
nsapi_error_t err = _at.at_cmd_discard("+USOCO", "=", "%d%s%d", socket->id, addr.get_ip_address(), addr.get_port());
if (err == NSAPI_ERROR_OK) {
socket->remoteAddress = addr;
socket->connected = true;
return NSAPI_ERROR_OK;
}
return NSAPI_ERROR_NO_CONNECTION;
}
nsapi_size_or_error_t UBLOX_AT_CellularStack::socket_sendto_impl(CellularSocket *socket, const SocketAddress &address,
const void *data, nsapi_size_t size)
{
MBED_ASSERT(socket->id != -1);
int sent_len = 0;
uint8_t ch = 0;
if (socket->proto == NSAPI_UDP) {
if (size > UBLOX_MAX_PACKET_SIZE) {
return NSAPI_ERROR_PARAMETER;
}
_at.cmd_start_stop("+USOST", "=", "%d%s%d%d", socket->id, address.get_ip_address(), address.get_port(), size);
_at.resp_start("@", true);
rtos::ThisThread::sleep_for(50ms);
_at.write_bytes((uint8_t *)data, size);
_at.resp_start("+USOST:");
_at.skip_param(); // skip socket id
sent_len = _at.read_int();
_at.resp_stop();
if ((_at.get_last_error() == NSAPI_ERROR_OK)) {
return sent_len;
}
} else if (socket->proto == NSAPI_TCP) {
bool success = true;
const char *buf = (const char *) data;
nsapi_size_t blk = UBLOX_MAX_PACKET_SIZE;
nsapi_size_t count = size;
while ((count > 0) && success) {
if (count < blk) {
blk = count;
}
_at.cmd_start_stop("+USOWR", "=", "%d%d", socket->id, blk);
_at.resp_start("@", true);
rtos::ThisThread::sleep_for(50ms);
_at.write_bytes((uint8_t *)buf, blk);
_at.resp_start("+USOWR:");
_at.skip_param(); // skip socket id
sent_len = _at.read_int();
_at.resp_stop();
if ((sent_len >= (int) blk) &&
(_at.get_last_error() == NSAPI_ERROR_OK)) {
} else {
success = false;
}
buf += blk;
count -= blk;
}
if (success && _at.get_last_error() == NSAPI_ERROR_OK) {
return size - count;
}
}
return _at.get_last_error();
}
nsapi_size_or_error_t UBLOX_AT_CellularStack::socket_recvfrom_impl(CellularSocket *socket, SocketAddress *address,
void *buffer, nsapi_size_t size)
{
MBED_ASSERT(socket->id != -1);
nsapi_size_or_error_t nsapi_error_size = NSAPI_ERROR_DEVICE_ERROR;
bool success = true;
nsapi_size_t read_blk;
nsapi_size_t count = 0;
nsapi_size_t usorf_sz;
char ipAddress[NSAPI_IP_SIZE];
uint8_t ch = 0;
int port = 0;
Timer timer;
if (socket->pending_bytes == 0) {
_at.process_oob();
if (socket->pending_bytes == 0) {
return NSAPI_ERROR_WOULD_BLOCK;
}
}
timer.start();
if (socket->proto == NSAPI_UDP) {
bool packet_received = false;
while (success && (size > 0 && !packet_received)) {
read_blk = UBLOX_MAX_PACKET_SIZE;
if (read_blk > size) {
read_blk = size;
}
if (socket->pending_bytes > 0) {
_at.cmd_start_stop("+USORF", "=", "%d%d", socket->id, read_blk);
_at.resp_start("+USORF:");
_at.skip_param(); // receiving socket id
_at.read_string(ipAddress, sizeof(ipAddress));
port = _at.read_int();
usorf_sz = _at.read_int();
if (usorf_sz > size) {
usorf_sz = size;
} else {
packet_received = true;
}
_at.read_bytes(&ch, 1);
_at.read_bytes((uint8_t *)buffer + count, usorf_sz);
_at.resp_stop();
// Must use what +USORF returns here as it may be less or more than we asked for
if (usorf_sz > socket->pending_bytes) {
socket->pending_bytes = 0;
} else {
socket->pending_bytes -= usorf_sz;
}
if (usorf_sz > 0) {
count += usorf_sz;
size -= usorf_sz;
} else {
// read() should not fail
success = false;
}
} else if (timer.elapsed_time() < SOCKET_TIMEOUT) {
// Wait for URCs
_at.process_oob();
} else {
if (count == 0) {
// Timeout with nothing received
success = false;
}
break;
}
}
} else if (socket->proto == NSAPI_TCP) {
while (success && (size > 0)) {
read_blk = UBLOX_MAX_PACKET_SIZE;
if (read_blk > size) {
read_blk = size;
}
if (socket->pending_bytes > 0) {
_at.cmd_start_stop("+USORD", "=", "%d%d", socket->id, read_blk);
_at.resp_start("+USORD:");
_at.skip_param(); // receiving socket id
usorf_sz = _at.read_int();
if (usorf_sz > size) {
usorf_sz = size;
}
_at.read_bytes(&ch, 1);
_at.read_bytes((uint8_t *)buffer + count, usorf_sz);
_at.resp_stop();
// Must use what +USORD returns here as it may be less or more than we asked for
if (usorf_sz > socket->pending_bytes) {
socket->pending_bytes = 0;
} else {
socket->pending_bytes -= usorf_sz;
}
if (usorf_sz > 0) {
count += usorf_sz;
size -= usorf_sz;
} else {
success = false;
}
} else if (timer.elapsed_time() < SOCKET_TIMEOUT) {
// Wait for URCs
_at.process_oob();
} else {
if (count == 0) {
// Timeout with nothing received
success = false;
}
break;
}
}
}
timer.stop();
socket->pending_bytes = 0;
if (!count || (_at.get_last_error() != NSAPI_ERROR_OK)) {
return NSAPI_ERROR_WOULD_BLOCK;
} else {
nsapi_error_size = count;
}
if (success && socket->proto == NSAPI_UDP && address) {
address->set_ip_address(ipAddress);
address->get_ip_address();
address->set_port(port);
}
return nsapi_error_size;
}
nsapi_error_t UBLOX_AT_CellularStack::socket_close_impl(int sock_id)
{
return _at.at_cmd_discard("+USOCL", "=", "%d", sock_id);
}
// Find or create a socket from the list.
UBLOX_AT_CellularStack::CellularSocket *UBLOX_AT_CellularStack::find_socket(int id)
{
CellularSocket *socket = NULL;
for (unsigned int x = 0; (socket == NULL) && (x < _device.get_property(AT_CellularDevice::PROPERTY_SOCKET_COUNT)); x++) {
if (_socket) {
if (_socket[x]->id == id) {
socket = (_socket[x]);
}
}
}
return socket;
}
// Clear out the storage for a socket
void UBLOX_AT_CellularStack::clear_socket(CellularSocket *socket)
{
if (socket != NULL) {
socket->id = SOCKET_UNUSED;
socket->started = false;
socket->pending_bytes = 0;
socket->closed = true;
if (socket->_cb) {
socket->_cb(socket->_data);
}
}
}
#ifndef UBX_MDM_SARA_R41XM
nsapi_error_t UBLOX_AT_CellularStack::get_ip_address(SocketAddress *address)
{
if (!address) {
return NSAPI_ERROR_PARAMETER;
}
_at.lock();
bool ipv4 = false, ipv6 = false;
_at.cmd_start_stop("+UPSND", "=", "%d%d", PROFILE, 0);
_at.resp_start("+UPSND:");
if (_at.info_resp()) {
_at.skip_param(2);
if (_at.read_string(_ip, PDP_IPV6_SIZE) != -1) {
convert_ipv6(_ip);
address->set_ip_address(_ip);
ipv4 = (address->get_ip_version() == NSAPI_IPv4);
ipv6 = (address->get_ip_version() == NSAPI_IPv6);
// Try to look for second address ONLY if modem has support for dual stack(can handle both IPv4 and IPv6 simultaneously).
// Otherwise assumption is that second address is not reliable, even if network provides one.
if ((_device.get_property(AT_CellularDevice::PROPERTY_IPV4V6_PDP_TYPE) && (_at.read_string(_ip, PDP_IPV6_SIZE) != -1))) {
convert_ipv6(_ip);
address->set_ip_address(_ip);
ipv6 = (address->get_ip_version() == NSAPI_IPv6);
}
}
}
_at.resp_stop();
_at.unlock();
if (ipv4 && ipv6) {
_stack_type = IPV4V6_STACK;
} else if (ipv4) {
_stack_type = IPV4_STACK;
} else if (ipv6) {
_stack_type = IPV6_STACK;
}
return (ipv4 || ipv6) ? NSAPI_ERROR_OK : NSAPI_ERROR_NO_ADDRESS;
}
#endif
nsapi_error_t UBLOX_AT_CellularStack::gethostbyname(const char *host, SocketAddress *address, nsapi_version_t version, const char *interface_name)
{
char ipAddress[NSAPI_IP_SIZE];
nsapi_error_t err = NSAPI_ERROR_DNS_FAILURE;
_at.lock();
if (address->set_ip_address(host)) {
err = NSAPI_ERROR_OK;
} else {
#ifdef UBX_MDM_SARA_R41XM
_at.set_at_timeout(70s);
#else
_at.set_at_timeout(120s);
#endif
// This interrogation can sometimes take longer than the usual 8 seconds
_at.cmd_start_stop("+UDNSRN", "=0,", "%s", host);
_at.resp_start("+UDNSRN:");
if (_at.info_resp()) {
_at.read_string(ipAddress, sizeof(ipAddress));
if (address->set_ip_address(ipAddress)) {
err = NSAPI_ERROR_OK;
}
}
_at.resp_stop();
_at.restore_at_timeout();
}
_at.unlock();
return err;
}

View File

@@ -0,0 +1,103 @@
/*
* 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_CELLULARSTACK_H_
#define UBLOX_AT_CELLULARSTACK_H_
#include <chrono>
#include "AT_CellularStack.h"
#include "CellularUtil.h"
#include "rtos/ThisThread.h"
#include "drivers/Timer.h"
using namespace std::chrono;
namespace mbed {
class UBLOX_AT_CellularStack : public AT_CellularStack {
public:
UBLOX_AT_CellularStack(ATHandler &atHandler, int cid, nsapi_ip_stack_t stack_type, AT_CellularDevice &device);
virtual ~UBLOX_AT_CellularStack();
#ifndef UBX_MDM_SARA_R41XM
virtual nsapi_error_t get_ip_address(SocketAddress *address);
#endif
virtual nsapi_error_t gethostbyname(const char *host,
SocketAddress *address, nsapi_version_t version = NSAPI_UNSPEC, const char *interface_name = NULL);
protected:
virtual nsapi_error_t socket_listen(nsapi_socket_t handle, int backlog);
virtual nsapi_error_t socket_accept(nsapi_socket_t server,
nsapi_socket_t *handle, SocketAddress *address = 0);
/** The profile to use (on board the modem).
*/
#define PROFILE 0
/** Socket "unused" value.
*/
static const int SOCKET_UNUSED = -1;
/** Socket timeout value in milliseconds.
* Note: the sockets layer above will retry the
* call to the functions here when they return NSAPI_ERROR_WOULD_BLOCK
* and the user has set a larger timeout or full blocking.
*/
static constexpr seconds SOCKET_TIMEOUT = 1s;
/** The maximum number of bytes in a packet that can be write/read from
* the AT interface in one go.
*/
static const int UBLOX_MAX_PACKET_SIZE = 1024;
virtual nsapi_error_t create_socket_impl(CellularSocket *socket);
virtual nsapi_error_t socket_connect(nsapi_socket_t handle, const SocketAddress &address);
virtual nsapi_size_or_error_t socket_sendto_impl(CellularSocket *socket, const SocketAddress &address,
const void *data, nsapi_size_t size);
virtual nsapi_size_or_error_t socket_recvfrom_impl(CellularSocket *socket, SocketAddress *address,
void *buffer, nsapi_size_t size);
virtual nsapi_error_t socket_close_impl(int sock_id);
private:
// URC handlers
void UUSORD_URC();
void UUSORF_URC();
void UUSOCL_URC();
void UUPSDD_URC();
/** Find a socket from the list.
*
* @param id Socket ID.
* @return Socket if True, otherwise NULL.
*/
CellularSocket *find_socket(int id = SOCKET_UNUSED);
/** Clear out the storage for a socket.
*
* @param id Cellular Socket.
* @return None
*/
void clear_socket(CellularSocket *socket);
};
} // namespace mbed
#endif /* UBLOX_AT_CELLULARSTACK_H_ */

View File

@@ -0,0 +1,29 @@
{
"name": "UBLOX_AT",
"config": {
"tx": {
"help": "TX pin for serial connection. D1 assumed if Arduino Form Factor, needs to be set/overwritten otherwise.",
"value": null
},
"rx": {
"help": "RX pin for serial connection. D0 assumed if Arduino Form Factor, needs to be set/overwritten otherwise.",
"value": null
},
"rts": {
"help": "RTS pin for serial connection",
"value": null
},
"cts": {
"help": "CTS pin for serial connection",
"value": null
},
"baudrate" : {
"help": "Serial connection baud rate",
"value": 115200
},
"provide-default": {
"help": "Provide as default CellularDevice [true/false]",
"value": false
}
}
}