Cellular: Remove netsocket/generic_modem_driver

pull/9472/head
Ari Parkkila 2018-12-18 23:11:32 -08:00
parent 139d506a24
commit 59972b6659
11 changed files with 5 additions and 2207 deletions

View File

@ -16,6 +16,11 @@
*/
#include "CellularContext.h"
MBED_WEAK CellularBase *CellularBase::get_target_default_instance()
{
return mbed::CellularContext::get_default_instance();
}
namespace mbed {
#ifdef CELLULAR_DEVICE
MBED_WEAK CellularContext *CellularContext::get_default_instance()

View File

@ -1,82 +0,0 @@
/* Copyright (c) 2017 ARM Limited
*
* 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 "mbed_toolchain.h"
#include "CellularBase.h"
#include "OnboardCellularInterface.h"
#ifndef CELLULAR_DEVICE
#if MODEM_ON_BOARD && MODEM_ON_BOARD_UART && NSAPI_PPP_AVAILABLE
#include "onboard_modem_api.h"
/**
* OnboardCellularInterface is an on-board specific implementation.
*
*/
OnboardCellularInterface::OnboardCellularInterface(bool debug) :
UARTCellularInterface(MDMTXD, MDMRXD, MDMDCD, MDMRTS,
MDMCTS, MDMRI, MDMDTR, MDMDSR,
MBED_CONF_PPP_CELL_IFACE_BAUD_RATE, MDM_PIN_POLARITY, debug)
{
}
OnboardCellularInterface::~OnboardCellularInterface()
{
}
void OnboardCellularInterface::modem_init()
{
::onboard_modem_init();
}
void OnboardCellularInterface::modem_deinit()
{
::onboard_modem_deinit();
}
void OnboardCellularInterface::modem_power_up()
{
::onboard_modem_power_up();
}
void OnboardCellularInterface::modem_power_down()
{
::onboard_modem_power_down();
}
#endif
#endif // CELLULAR_DEVICE
#ifdef CELLULAR_DEVICE
MBED_WEAK CellularBase *CellularBase::get_target_default_instance()
{
return CellularContext::get_default_instance();
}
#elif defined ONBOARD_CELLULAR_INTERFACE_AVAILABLE
MBED_WEAK CellularBase *CellularBase::get_target_default_instance()
{
static OnboardCellularInterface cellular;
return &cellular;
}
#else
MBED_WEAK CellularBase *CellularBase::get_target_default_instance()
{
return NULL;
}
#endif

View File

@ -1,174 +0,0 @@
/* Copyright (c) 2017 ARM Limited
*
* 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 ONBOARD_CELLULAR_INTERFACE_
#define ONBOARD_CELLULAR_INTERFACE_
#include "CellularContext.h"
#ifdef CELLULAR_DEVICE
using namespace mbed;
MBED_DEPRECATED_SINCE("mbed-os-5.9", "This API will be deprecated, use CellularBase::get_default_instance() instead.")
class OnboardCellularInterface : public CellularBase {
public:
OnboardCellularInterface(bool debug = false)
{
context = CellularContext::get_default_instance();
MBED_ASSERT(context != NULL);
CellularDevice *dev = CellularDevice::get_default_instance();
MBED_ASSERT(dev != NULL);
dev->modem_debug_on(debug);
}
public: // from NetworkInterface
virtual nsapi_error_t set_blocking(bool blocking)
{
return context->set_blocking(blocking);
}
virtual NetworkStack *get_stack()
{
return context->get_stack();
}
virtual const char *get_ip_address()
{
return context->get_ip_address();
}
virtual void attach(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb)
{
context->attach(status_cb);
}
virtual nsapi_error_t connect()
{
return context->connect();
}
virtual nsapi_error_t disconnect()
{
return context->disconnect();
}
// from CellularBase
virtual void set_plmn(const char *plmn)
{
context->set_plmn(plmn);
}
virtual void set_sim_pin(const char *sim_pin)
{
context->set_sim_pin(sim_pin);
}
virtual nsapi_error_t connect(const char *sim_pin, const char *apn = 0, const char *uname = 0,
const char *pwd = 0)
{
return context->connect(sim_pin, apn, uname, pwd);
}
virtual void set_credentials(const char *apn, const char *uname = 0, const char *pwd = 0)
{
context->set_credentials(apn, uname, pwd);
}
virtual const char *get_netmask()
{
return context->get_netmask();
}
virtual const char *get_gateway()
{
return context->get_gateway();
}
virtual bool is_connected()
{
return context->is_connected();
}
private:
CellularContext *context;
};
#define ONBOARD_CELLULAR_INTERFACE_AVAILABLE
#elif MODEM_ON_BOARD && MODEM_ON_BOARD_UART && NSAPI_PPP_AVAILABLE
#include "UARTCellularInterface.h"
/** OnboardCellularInterface class
*
* @deprecated This API will be deprecated in mbed-os-5.9. Use mbed-os/features/cellular/framework/API/CellularPower.h instead.
*
* This interface serves as the controller/driver for an
* onboard modem implementing onboard_modem_api.h.
*
* Depending on the type of on-board modem, OnboardCellularInterface
* could be derived from different implementation classes.
* Portable applications should only rely on it being a CellularBase.
*/
class OnboardCellularInterface : public UARTCellularInterface {
public:
/** Constructor
* @deprecated This API will be deprecated in mbed-os-5.9. Use mbed-os/features/cellular/framework/API/CellularPower.h instead.
*/
MBED_DEPRECATED_SINCE("mbed-os-5.9", "This API will be deprecated, use mbed-os/features/cellular/framework/API/CellularPower.h instead.")
OnboardCellularInterface(bool debug = false);
/** Destructor
* @deprecated This API will be deprecated in mbed-os-5.9. Use mbed-os/features/cellular/framework/API/CellularPower.h instead.
*/
MBED_DEPRECATED_SINCE("mbed-os-5.9", "This API will be deprecated, use mbed-os/features/cellular/framework/API/CellularPower.h instead.")
virtual ~OnboardCellularInterface();
protected:
/** Sets the modem up for powering on
*
* @deprecated This API will be deprecated in mbed-os-5.9. Use mbed-os/features/cellular/framework/API/CellularPower.h instead.
*
* modem_init() is equivalent to plugging in the device, for example, attaching power and serial port.
* Uses onboard_modem_api.h where the target provides the implementation of onboard_modem_api.
*/
MBED_DEPRECATED_SINCE("mbed-os-5.9", "This API will be deprecated, use mbed-os/features/cellular/framework/API/CellularPower.h instead.")
virtual void modem_init();
/** Sets the modem in unplugged state
*
* @deprecated This API will be deprecated in mbed-os-5.9. Use mbed-os/features/cellular/framework/API/CellularPower.h instead.
*
* modem_deinit() will be equivalent to pulling the plug off of the device, in other words, detaching power
* and serial port. This puts the modem in lowest power state.
* Uses onboard_modem_api.h where the target provides the implementation of onboard_modem_api.
*/
MBED_DEPRECATED_SINCE("mbed-os-5.9", "This API will be deprecated, use mbed-os/features/cellular/framework/API/CellularPower.h instead.")
virtual void modem_deinit();
/** Powers up the modem
*
* @deprecated This API will be deprecated in mbed-os-5.9. Use mbed-os/features/cellular/framework/API/CellularPower.h instead.
*
* modem_power_up() is equivalent to pressing the soft power button.
* The driver may repeat this if the modem is not responsive to AT commands.
* Uses onboard_modem_api.h where the target provides the implementation of onboard_modem_api.
*/
MBED_DEPRECATED_SINCE("mbed-os-5.9", "This API will be deprecated, use mbed-os/features/cellular/framework/API/CellularPower.h instead.")
virtual void modem_power_up();
/** Powers down the modem
*
* @deprecated This API will be deprecated in mbed-os-5.9. Use mbed-os/features/cellular/framework/API/CellularPower.h instead.
*
* modem_power_down() is equivalent to turning off the modem by button press.
* Uses onboard_modem_api.h where the target provides the implementation of onboard_modem_api.
*/
MBED_DEPRECATED_SINCE("mbed-os-5.9", "This API will be deprecated, use mbed-os/features/cellular/framework/API/CellularPower.h instead.")
virtual void modem_power_down();
};
#define ONBOARD_CELLULAR_INTERFACE_AVAILABLE
#endif //MODEM_ON_BOARD && MODEM_ON_BOARD_UART && NSAPI_PPP_AVAILABLE
#endif //ONBOARD_CELLULAR_INTERFACE_

View File

@ -1,849 +0,0 @@
/* Copyright (c) 2017 ARM Limited
*
* 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 "PPPCellularInterface.h"
#if NSAPI_PPP_AVAILABLE
#include <string.h>
#include "nsapi_ppp.h"
#if MBED_CONF_PPP_CELL_IFACE_APN_LOOKUP
#include "APN_db.h"
#endif //MBED_CONF_PPP_CELL_IFACE_APN_LOOKUP
#include "mbed_trace.h"
#define TRACE_GROUP "UCID"
#include "mbed_wait_api.h"
using namespace mbed;
/**
* PDP (packet data profile) Context
*/
#define CTX "1"
/**
* Output Enter sequence for the modem , default CR
*/
#define OUTPUT_ENTER_KEY "\r"
#if MBED_CONF_PPP_CELL_IFACE_AT_PARSER_BUFFER_SIZE
#define AT_PARSER_BUFFER_SIZE MBED_CONF_PPP_CELL_IFACE_AT_PARSER_BUFFER_SIZE //bytes
#else
#define AT_PARSER_BUFFER_SIZE 256 //bytes
#endif //MBED_CONF_PPP_CELL_IFACE_AT_PARSER_BUFFER_SIZE
#if MBED_CONF_PPP_CELL_IFACE_AT_PARSER_TIMEOUT
#define AT_PARSER_TIMEOUT MBED_CONF_PPP_CELL_IFACE_AT_PARSER_TIMEOUT
#else
#define AT_PARSER_TIMEOUT 8*1000 //miliseconds
#endif //MBED_CONF_PPP_CELL_IFACE_AT_PARSER_TIMEOUT
static bool initialized;
static bool set_sim_pin_check_request;
static bool change_pin;
static device_info dev_info;
static void parser_abort(ATCmdParser *at)
{
at->abort();
}
static bool get_CCID(ATCmdParser *at)
{
// Returns the ICCID (Integrated Circuit Card ID) of the SIM-card.
// ICCID is a serial number identifying the SIM.
bool success = at->send("AT+CCID") && at->recv("+CCID: %20[^\n]\nOK\n", dev_info.ccid);
tr_debug("DevInfo: CCID=%s", dev_info.ccid);
return success;
}
static bool get_IMSI(ATCmdParser *at)
{
// International mobile subscriber identification
bool success = at->send("AT+CIMI") && at->recv("%15[^\n]\nOK\n", dev_info.imsi);
tr_debug("DevInfo: IMSI=%s", dev_info.imsi);
return success;
}
static bool get_IMEI(ATCmdParser *at)
{
// International mobile equipment identifier
bool success = at->send("AT+CGSN") && at->recv("%15[^\n]\nOK\n", dev_info.imei);
tr_debug("DevInfo: IMEI=%s", dev_info.imei);
return success;
}
static bool get_MEID(ATCmdParser *at)
{
// Mobile equipment identifier
bool success = at->send("AT+GSN")
&& at->recv("%18[^\n]\nOK\n", dev_info.meid);
tr_debug("DevInfo: MEID=%s", dev_info.meid);
return success;
}
static bool set_CMGF(ATCmdParser *at)
{
// Preferred message format
// set AT+CMGF=[mode] , 0 PDU mode, 1 text mode
bool success = at->send("AT+CMGF=1") && at->recv("OK");
return success;
}
static bool set_CNMI(ATCmdParser *at)
{
// New SMS indication configuration
// set AT+CMTI=[mode, index] , 0 PDU mode, 1 text mode
// Multiple URCs for SMS, i.e., CMT, CMTI, UCMT, CBMI, CDSI as DTE could be following any of these SMS formats
bool success = at->send("AT+CNMI=2," CTX) && at->recv("OK");
return success;
}
static void CMTI_URC(ATCmdParser *at)
{
// our CMGF = 1, i.e., text mode. So we expect response in this format:
//+CMTI: <mem>,<index>,
at->recv(": %*u,%*u");
tr_info("New SMS received");
}
static void CMT_URC(ATCmdParser *at)
{
// our CMGF = 1, i.e., text mode. So we expect response in this format:
//+CMT: <oa>,[<alpha>],<scts>[,<tooa>,
//<fo>,<pid>,<dcs>,<sca>,<tosca>,
//<length>]<CR><LF><data>
// By default detailed SMS header CSDH=0 , so we are not expecting [,<tooa>,
//<fo>,<pid>,<dcs>,<sca>,<tosca>
char sms[50];
char service_timestamp[15];
at->recv(": %49[^\"]\",,%14[^\"]\"\n", sms, service_timestamp);
tr_info("SMS:%s, %s", service_timestamp, sms);
}
static bool set_atd(ATCmdParser *at)
{
bool success = at->send("ATD*99***" CTX "#") && at->recv("CONNECT");
return success;
}
/**
* Enables or disables SIM pin check lock
*/
static nsapi_error_t do_sim_pin_check(ATCmdParser *at, const char *pin)
{
bool success;
if (set_sim_pin_check_request) {
/* use the SIM locked */
success = at->send("AT+CLCK=\"SC\",1,\"%s\"", pin) && at->recv("OK");
} else {
/* use the SIM unlocked */
success = at->send("AT+CLCK=\"SC\",0,\"%s\"", pin) && at->recv("OK");
}
if (success) {
return NSAPI_ERROR_OK;
}
return NSAPI_ERROR_AUTH_FAILURE;
}
/**
* Change the pin code for the SIM card
*/
static nsapi_error_t do_change_sim_pin(ATCmdParser *at, const char *old_pin, const char *new_pin)
{
/* changes the SIM pin */
bool success = at->send("AT+CPWD=\"SC\",\"%s\",\"%s\"", old_pin, new_pin) && at->recv("OK");
if (success) {
return NSAPI_ERROR_OK;
}
return NSAPI_ERROR_AUTH_FAILURE;
}
static void set_nwk_reg_status_csd(unsigned int status)
{
switch (status) {
case CSD_NOT_REGISTERED_NOT_SEARCHING:
case CSD_NOT_REGISTERED_SEARCHING:
break;
case CSD_REGISTERED:
case CSD_REGISTERED_ROAMING:
tr_debug("Registered for circuit switched service");
break;
case CSD_REGISTRATION_DENIED:
tr_debug("Circuit switched service denied");
break;
case CSD_UNKNOWN_COVERAGE:
tr_debug("Out of circuit switched service coverage");
break;
case CSD_SMS_ONLY:
tr_debug("SMS service only");
break;
case CSD_SMS_ONLY_ROAMING:
tr_debug("SMS service only");
break;
case CSD_CSFB_NOT_PREFERRED:
tr_debug("Registered for circuit switched service with CSFB not preferred");
break;
default:
tr_debug("Unknown circuit switched service registration status. %u", status);
break;
}
dev_info.reg_status_csd = static_cast<nwk_registration_status_csd>(status);
}
static void set_nwk_reg_status_psd(unsigned int status)
{
switch (status) {
case PSD_NOT_REGISTERED_NOT_SEARCHING:
case PSD_NOT_REGISTERED_SEARCHING:
break;
case PSD_REGISTERED:
case PSD_REGISTERED_ROAMING:
tr_debug("Registered for packet switched service");
break;
case PSD_REGISTRATION_DENIED:
tr_debug("Packet switched service denied");
break;
case PSD_UNKNOWN_COVERAGE:
tr_debug("Out of packet switched service coverage");
break;
case PSD_EMERGENCY_SERVICES_ONLY:
tr_debug("Limited access for packet switched service. Emergency use only.");
break;
default:
tr_debug("Unknown packet switched service registration status. %u", status);
break;
}
dev_info.reg_status_psd = static_cast<nwk_registration_status_psd>(status);
}
static bool is_registered_csd()
{
return (dev_info.reg_status_csd == CSD_REGISTERED) ||
(dev_info.reg_status_csd == CSD_REGISTERED_ROAMING) ||
(dev_info.reg_status_csd == CSD_CSFB_NOT_PREFERRED);
}
static bool is_registered_psd()
{
return (dev_info.reg_status_psd == PSD_REGISTERED) ||
(dev_info.reg_status_psd == PSD_REGISTERED_ROAMING);
}
PPPCellularInterface::PPPCellularInterface(FileHandle *fh, bool debug)
{
_new_pin = NULL;
_pin = NULL;
_at = NULL;
_apn = NULL;
_uname = NULL;
_pwd = NULL;
_fh = fh;
_debug_trace_on = debug;
_stack = DEFAULT_STACK;
_connection_status_cb = NULL;
_connect_status = NSAPI_STATUS_DISCONNECTED;
_connect_is_blocking = true;
dev_info.reg_status_csd = CSD_NOT_REGISTERED_NOT_SEARCHING;
dev_info.reg_status_psd = PSD_NOT_REGISTERED_NOT_SEARCHING;
}
PPPCellularInterface::~PPPCellularInterface()
{
delete _at;
}
void PPPCellularInterface::enable_hup(bool)
{
//meant to be overridden
}
void PPPCellularInterface::modem_init()
{
//meant to be overridden
}
void PPPCellularInterface::modem_deinit()
{
//meant to be overridden
}
void PPPCellularInterface::modem_power_up()
{
//meant to be overridden
}
void PPPCellularInterface::modem_power_down()
{
//meant to be overridden
}
void PPPCellularInterface::modem_debug_on(bool on)
{
_debug_trace_on = on;
}
void PPPCellularInterface::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);
}
}
/**
* Public API. Sets up the flag for the driver to enable or disable SIM pin check
* at the next boot.
*/
void PPPCellularInterface::set_sim_pin_check(bool check)
{
set_sim_pin_check_request = check;
}
/**
* Public API. Sets up the flag for the driver to change pin code for SIM card
*/
void PPPCellularInterface::set_new_sim_pin(const char *new_pin)
{
change_pin = true;
_new_pin = new_pin;
}
bool PPPCellularInterface::nwk_registration(uint8_t nwk_type)
{
bool success = false;
bool registered = false;
char str[35];
int retcode;
int retry_counter = 0;
unsigned int reg_status;
success = nwk_type == PACKET_SWITCHED ?
_at->send("AT+CGREG=0") :
_at->send("AT+CREG=0") && _at->recv("OK\n");
success = _at->send("AT+COPS=0") //initiate auto-registration
&& _at->recv("OK");
if (!success) {
tr_error("Modem not responding.");
return false;
}
//Network search
//If not registered after 60 attempts, i.e., 30 seconds wait, give up
tr_debug("Searching Network ...");
while (!registered) {
if (retry_counter > 60) {
success = false;
goto give_up;
}
success = nwk_type == PACKET_SWITCHED ?
_at->send("AT+CGREG?")
&& _at->recv("+CGREG: %34[^\n]\n", str)
&& _at->recv("OK\n") :
_at->send("AT+CREG?")
&& _at->recv("+CREG: %34[^\n]\n", str)
&& _at->recv("OK\n");
retcode = sscanf(str, "%*u,%u", &reg_status);
if (retcode >= 1) {
if (nwk_type == PACKET_SWITCHED) {
set_nwk_reg_status_psd(reg_status);
if (is_registered_psd()) {
registered = true;
}
} else if (nwk_type == CIRCUIT_SWITCHED) {
set_nwk_reg_status_csd(reg_status);
if (is_registered_csd()) {
registered = true;
}
}
}
if (registered) {
break;
} else {
wait_ms(500);
}
retry_counter++;
}
give_up:
return registered;
}
bool PPPCellularInterface::is_connected()
{
return (_connect_status == NSAPI_STATUS_GLOBAL_UP || _connect_status == NSAPI_STATUS_LOCAL_UP);
}
// Get the SIM card going.
nsapi_error_t PPPCellularInterface::initialize_sim_card()
{
nsapi_error_t nsapi_error = NSAPI_ERROR_AUTH_FAILURE;
int retry_count = 0;
bool done = false;
/* SIM initialization may take a significant amount, so an error is
* kind of expected. We should retry 10 times until we succeed or timeout. */
for (retry_count = 0; !done && (retry_count < 10); retry_count++) {
char pinstr[16];
if (_at->send("AT+CPIN?") && _at->recv("+CPIN: %15[^\n]\nOK\n", pinstr)) {
if (strcmp(pinstr, "SIM PIN") == 0) {
if (!_at->send("AT+CPIN=\"%s\"", _pin) || !_at->recv("OK")) {
tr_debug("PIN correct");
nsapi_error = NSAPI_ERROR_OK;
}
} else if (strcmp(pinstr, "READY") == 0) {
tr_debug("SIM Ready");
nsapi_error = NSAPI_ERROR_OK;
done = true;
} else {
tr_debug("Unexpected response from SIM: \"%s\"", pinstr);
}
}
/* wait for a second before retry */
wait_ms(1000);
}
if (!done) {
tr_error("SIM not ready.");
}
return nsapi_error;
}
void PPPCellularInterface::set_sim_pin(const char *pin)
{
/* overwrite the default pin by user provided pin */
_pin = pin;
}
nsapi_error_t PPPCellularInterface::setup_context_and_credentials()
{
bool success;
if (!_apn) {
return NSAPI_ERROR_PARAMETER;
}
#if NSAPI_PPP_IPV4_AVAILABLE && NSAPI_PPP_IPV6_AVAILABLE
const char ipv4v6_pdp_type[] = {"IPV4V6"};
const char ipv4_pdp_type[] = {"IP"};
const char *pdp_type = ipv4v6_pdp_type;
_stack = IPV4V6_STACK;
#elif NSAPI_PPP_IPV6_AVAILABLE
const char pdp_type[] = {"IPV6"};
#elif NSAPI_PPP_IPV4_AVAILABLE
const char pdp_type[] = {"IP"};
#endif
const char *auth = _uname && _pwd ? "CHAP:" : "";
#if NSAPI_PPP_IPV4_AVAILABLE && NSAPI_PPP_IPV6_AVAILABLE
retry_without_dual_stack:
#endif
success = _at->send("AT"
"+FCLASS=0;" // set to connection (ATD) to data mode
"+CGDCONT=" CTX ",\"%s\",\"%s%s\"",
pdp_type, auth, _apn
)
&& _at->recv("OK");
#if NSAPI_PPP_IPV4_AVAILABLE && NSAPI_PPP_IPV6_AVAILABLE
if (_stack == IPV4V6_STACK) {
if (!success) {
// fallback to ipv4
pdp_type = ipv4_pdp_type;
_stack = IPV4_STACK;
goto retry_without_dual_stack;
}
}
#endif
if (!success) {
_at->recv("OK");
}
return success ? NSAPI_ERROR_OK : NSAPI_ERROR_PARAMETER;
}
void PPPCellularInterface::set_credentials(const char *apn, const char *uname,
const char *pwd)
{
_apn = apn;
_uname = uname;
_pwd = pwd;
}
void PPPCellularInterface::setup_at_parser()
{
if (_at) {
return;
}
_at = new ATCmdParser(_fh, OUTPUT_ENTER_KEY, AT_PARSER_BUFFER_SIZE, AT_PARSER_TIMEOUT,
_debug_trace_on ? true : false);
/* Error cases, out of band handling */
_at->oob("ERROR", callback(parser_abort, _at));
_at->oob("+CME ERROR", callback(parser_abort, _at));
_at->oob("+CMS ERROR", callback(parser_abort, _at));
_at->oob("NO CARRIER", callback(parser_abort, _at));
/* URCs, handled out of band */
_at->oob("+CMT", callback(CMT_URC, _at));
_at->oob("+CMTI", callback(CMTI_URC, _at));
}
void PPPCellularInterface::shutdown_at_parser()
{
delete _at;
_at = NULL;
}
nsapi_error_t PPPCellularInterface::connect(const char *sim_pin, const char *apn, const char *uname, const char *pwd)
{
if (!sim_pin) {
return NSAPI_ERROR_PARAMETER;
}
_pin = sim_pin;
if (apn) {
if (pwd && !uname) {
return NSAPI_ERROR_PARAMETER;
}
set_credentials(apn, uname, pwd);
}
return connect();
}
nsapi_error_t PPPCellularInterface::connect()
{
nsapi_error_t retcode;
bool success;
bool did_init = false;
const char *apn_config = NULL;
bool user_specified_apn = false;
/* If the user has specified the APN then use that or,
* if we are not using the APN database, set _apn to
* "internet" as a best guess
*/
if (_apn) {
user_specified_apn = true;
} else {
#ifndef MBED_CONF_PPP_CELL_IFACE_APN_LOOKUP
_apn = "internet";
user_specified_apn = true;
#endif
}
if (is_connected()) {
return NSAPI_ERROR_IS_CONNECTED;
} else if (_connect_status == NSAPI_STATUS_CONNECTING) {
return NSAPI_ERROR_ALREADY;
}
_connect_status = NSAPI_STATUS_CONNECTING;
if (_connection_status_cb) {
_connection_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_CONNECTING);
}
do {
retry_init:
retcode = NSAPI_ERROR_OK;
/* setup AT parser */
setup_at_parser();
if (!initialized) {
/* If we have hangup (eg DCD) detection, we don't want it active
* as long as we are using ATCmdParser.
* As soon as we get into data mode, we will turn it back on. */
enable_hup(false);
if (!power_up()) {
retcode = NSAPI_ERROR_DEVICE_ERROR;
break;
}
retcode = initialize_sim_card();
if (retcode != NSAPI_ERROR_OK) {
break;
}
success = nwk_registration(PACKET_SWITCHED) //perform network registration
&& get_CCID(_at)//get integrated circuit ID of the SIM
&& get_IMSI(_at)//get international mobile subscriber information
&& get_IMEI(_at)//get international mobile equipment identifier
&& get_MEID(_at)//its same as IMEI
&& set_CMGF(_at)//set message format for SMS
&& set_CNMI(_at);//set new SMS indication
if (!success) {
retcode = NSAPI_ERROR_NO_CONNECTION;
break;
}
#if MBED_CONF_PPP_CELL_IFACE_APN_LOOKUP
if (!apn_config) {
apn_config = apnconfig(dev_info.imsi);
}
#endif
/* Check if user want skip SIM pin checking on boot up */
if (set_sim_pin_check_request) {
retcode = do_sim_pin_check(_at, _pin);
if (retcode != NSAPI_ERROR_OK) {
break;
}
/* set this request to false, as it is unnecessary to repeat in case of retry */
set_sim_pin_check_request = false;
}
/* check if the user requested a sim pin change */
if (change_pin) {
retcode = do_change_sim_pin(_at, _pin, _new_pin);
if (retcode != NSAPI_ERROR_OK) {
break;
}
/* set this request to false, as it is unnecessary to repeat in case of retry */
change_pin = false;
}
#if MBED_CONF_PPP_CELL_IFACE_APN_LOOKUP
if (!user_specified_apn && apn_config) {
_apn = _APN_GET(apn_config);
_uname = _APN_GET(apn_config);
_pwd = _APN_GET(apn_config);
tr_info("Looked up APN %s.", _apn);
}
#endif
//sets up APN and IP protocol for external PDP context
retcode = setup_context_and_credentials();
if (retcode != NSAPI_ERROR_OK) {
break;
}
if (!success) {
shutdown_at_parser();
retcode = NSAPI_ERROR_NO_CONNECTION;
break;
}
initialized = true;
did_init = true;
} else {
/* If we were already initialized, we expect to receive NO_CARRIER response
* from the modem as we were kicked out of Data mode */
_at->recv("NO CARRIER");
success = _at->send("AT") && _at->recv("OK");
}
tr_info("The APN being used is %s.\n", _apn);
/* Attempt to enter data mode */
success = set_atd(_at); //enter into Data mode with the modem
if (!success) {
power_down();
initialized = false;
/* if we were previously initialized , i.e., not in this particular attempt,
* we want to re-initialize */
if (!did_init) {
goto retry_init;
}
/* shutdown AT parser before notifying application of the failure */
shutdown_at_parser();
retcode = NSAPI_ERROR_NO_CONNECTION;
break;
}
/* This is the success case.
* Save RAM, discard AT Parser as we have entered Data mode. */
shutdown_at_parser();
/* We now want hangup (e.g., DCD) detection if available */
enable_hup(true);
/* Initialize PPP
* mbed_ppp_init() is a blocking call, it will block until
* connected, or timeout after 30 seconds*/
retcode = nsapi_ppp_connect(_fh, callback(this, &PPPCellularInterface::ppp_status_cb), _uname, _pwd, _stack);
if (retcode == NSAPI_ERROR_OK && _connect_is_blocking) {
_connect_status = NSAPI_STATUS_GLOBAL_UP;
}
} while ((_connect_status == NSAPI_STATUS_CONNECTING && _connect_is_blocking) &&
apn_config && *apn_config);
if (retcode != NSAPI_ERROR_OK) {
_connect_status = NSAPI_STATUS_DISCONNECTED;
if (_connection_status_cb) {
_connection_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_DISCONNECTED);
}
}
return retcode;
}
/**
* User initiated disconnect
*
* Disconnects from PPP connection only and brings down the underlying network
* interface
*/
nsapi_error_t PPPCellularInterface::disconnect()
{
return nsapi_ppp_disconnect(_fh);
}
const char *PPPCellularInterface::get_ip_address()
{
return nsapi_ppp_get_ip_addr(_fh);
}
const char *PPPCellularInterface::get_netmask()
{
return nsapi_ppp_get_netmask(_fh);
}
const char *PPPCellularInterface::get_gateway()
{
return nsapi_ppp_get_gw_addr(_fh);
}
/** Power down modem
* Uses AT command to do it */
void PPPCellularInterface::power_down()
{
modem_power_down();
modem_deinit();
}
/**
* Powers up the modem
*
* Enables the GPIO lines to the modem and then wriggles the power line in short pulses.
*/
bool PPPCellularInterface::power_up()
{
/* Initialize GPIO lines */
modem_init();
/* Give modem a little time to settle down */
wait(0.25);
bool success = false;
int retry_count = 0;
while (true) {
modem_power_up();
/* Modem tends to spit out noise during power up - don't confuse the parser */
_at->flush();
/* It is mandatory to avoid sending data to the serial port during the first 200 ms
* of the module startup. Telit_xE910 Global form factor App note.
* Not necessary for all types of modems however. Let's wait just to be on the safe side */
wait_ms(200);
_at->set_timeout(1000);
if (_at->send("AT") && _at->recv("OK")) {
tr_info("Modem Ready.");
break;
}
if (++retry_count > 10) {
goto failure;
}
}
_at->set_timeout(8000);
/*For more details regarding DCD and DTR circuitry, please refer to Modem AT manual */
success = _at->send("AT"
"E0;" //turn off modem echoing
"+CMEE=2;"//turn on verbose responses
"&K0"//turn off RTC/CTS handshaking
"+IPR=115200;"//setup baud rate
"&C1;"//set DCD circuit(109), changes in accordance with the carrier detect status
"&D0")//set DTR circuit, we ignore the state change of DTR
&& _at->recv("OK");
if (!success) {
goto failure;
}
/* If everything alright, return from here with success*/
return success;
failure:
tr_error("Preliminary modem setup failed.");
return false;
}
/**
* Get a pointer to the underlying network stack
*/
NetworkStack *PPPCellularInterface::get_stack()
{
return nsapi_ppp_get_stack();
}
void PPPCellularInterface::attach(
Callback<void(nsapi_event_t, intptr_t)> status_cb)
{
_connection_status_cb = status_cb;
}
nsapi_connection_status_t PPPCellularInterface::get_connection_status() const
{
return _connect_status;
}
nsapi_error_t PPPCellularInterface::set_blocking(bool blocking)
{
return nsapi_ppp_set_blocking(blocking);
}
#endif // NSAPI_PPP_AVAILABLE

View File

@ -1,414 +0,0 @@
/* Copyright (c) 2017 ARM Limited
*
* 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 PPP_CELLULAR_INTERFACE_
#define PPP_CELLULAR_INTERFACE_
#include "CellularBase.h"
#include "platform/ATCmdParser.h"
#include "ATCmdParser.h"
#include "FileHandle.h"
#include "Callback.h"
#if NSAPI_PPP_AVAILABLE
// Forward declaration
class NetworkStack;
/**
* Network registration status
* UBX-13001820 - AT Commands Example Application Note (Section 4.1.4.5)
*/
typedef enum {
GSM = 0,
COMPACT_GSM = 1,
UTRAN = 2,
EDGE = 3,
HSDPA = 4,
HSUPA = 5,
HSDPA_HSUPA = 6,
LTE = 7
} radio_access_nwk_type;
/**
* Used in registration process to tell which type of network
* to connect.
*/
typedef enum {
CIRCUIT_SWITCHED = 0,
PACKET_SWITCHED
} nwk_type;
/**
* Circuit Switched network registration status (CREG Usage)
* UBX-13001820 - AT Commands Example Application Note (Section 7.10.3)
*/
typedef enum {
CSD_NOT_REGISTERED_NOT_SEARCHING = 0,
CSD_REGISTERED = 1,
CSD_NOT_REGISTERED_SEARCHING = 2,
CSD_REGISTRATION_DENIED = 3,
CSD_UNKNOWN_COVERAGE = 4,
CSD_REGISTERED_ROAMING = 5,
CSD_SMS_ONLY = 6,
CSD_SMS_ONLY_ROAMING = 7,
CSD_CSFB_NOT_PREFERRED = 9
} nwk_registration_status_csd;
/**
* Packet Switched network registration status (CGREG Usage)
* UBX-13001820 - AT Commands Example Application Note (Section 18.27.3)
*/
typedef enum {
PSD_NOT_REGISTERED_NOT_SEARCHING = 0,
PSD_REGISTERED = 1,
PSD_NOT_REGISTERED_SEARCHING = 2,
PSD_REGISTRATION_DENIED = 3,
PSD_UNKNOWN_COVERAGE = 4,
PSD_REGISTERED_ROAMING = 5,
PSD_EMERGENCY_SERVICES_ONLY = 8
} nwk_registration_status_psd;
typedef struct {
char ccid[20 + 1]; //!< Integrated Circuit Card ID
char imsi[15 + 1]; //!< International Mobile Station Identity
char imei[15 + 1]; //!< International Mobile Equipment Identity
char meid[18 + 1]; //!< Mobile Equipment IDentifier
int flags;
radio_access_nwk_type rat;
nwk_registration_status_csd reg_status_csd;
nwk_registration_status_psd reg_status_psd;
} device_info;
/** PPPCellularInterface class
*
* @deprecated This API will be deprecated in mbed-os-5.9. Use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.
*
* This interface serves as the controller/driver for the Cellular
* modems (tested with UBLOX_C027 and MTS_DRAGONFLY_F411RE).
*
* The driver will work with any generic FileHandle, and can be
* derived from in order to provide forms for specific interfaces, as well as
* adding extra power and reset controls alongside the FileHandle.
*/
class PPPCellularInterface : public CellularBase {
public:
/** Constructor for a generic modem, using a single FileHandle for commands and PPP data.
*
* @deprecated This API will be deprecated in mbed-os-5.9. Use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.
*
* The file handle pointer is not accessed within the constructor, only recorded for later
* use - this permits a derived class to pass a pointer to a not-yet-constructed member object.
*/
MBED_DEPRECATED_SINCE("mbed-os-5.9", "This API will be deprecated, use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.")
PPPCellularInterface(mbed::FileHandle *fh, bool debug = false);
/** Destructor
*
* @deprecated This API will be deprecated in mbed-os-5.9. Use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.
*/
MBED_DEPRECATED_SINCE("mbed-os-5.9", "This API will be deprecated, use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.")
virtual ~PPPCellularInterface();
/** Set the Cellular network credentials
*
* @deprecated This API will be deprecated in mbed-os-5.9. Use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.
*
* Please check documentation of connect() for default behavior of APN settings.
*
* @param apn Access point name
* @param uname optionally, Username
* @param pwd optionally, password
*/
MBED_DEPRECATED_SINCE("mbed-os-5.9", "This API will be deprecated, use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.")
virtual void set_credentials(const char *apn, const char *uname = 0,
const char *pwd = 0);
/** Set the pin code for SIM card
*
* @deprecated This API will be deprecated in mbed-os-5.9. Use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.
*
* @param sim_pin PIN for the SIM card
*/
MBED_DEPRECATED_SINCE("mbed-os-5.9", "This API will be deprecated, use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.")
virtual void set_sim_pin(const char *sim_pin);
/** Start the interface
*
* @deprecated This API will be deprecated in mbed-os-5.9. Use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.
*
* Attempts to connect to a Cellular network.
* This driver is written mainly for data network connections as CellularBase
* is NetworkInterface. That's why connect() call internally calls nwk_registration()
* method with parameter PACKET_SWITCHED network. Circuit switched hook and registration
* process is implemented and left in the driver for future extension/subclass support,e.g.,
* an SMS or GPS extension.
*
* @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
*/
MBED_DEPRECATED_SINCE("mbed-os-5.9", "This API will be deprecated, use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.")
virtual nsapi_error_t connect(const char *sim_pin, const char *apn = 0,
const char *uname = 0, const char *pwd = 0);
/** Attempt to connect to the Cellular network
*
* @deprecated This API will be deprecated in mbed-os-5.9. Use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.
*
* Brings up the network interface. Connects to the Cellular Radio
* network and then brings up the underlying network stack to be used
* by the cellular modem over PPP interface.
*
* If the SIM requires a PIN, and it is not set/invalid, NSAPI_ERROR_AUTH_ERROR is returned.
* For APN setup, default behavior is to use 'internet' as APN string and assuming no authentication
* is required, i.e., username and password are not set. Optionally, a database lookup can be requested
* by turning on the APN database lookup feature. In order to do so, add 'MBED_CONF_PPP_CELL_IFACE_APN_LOOKUP'
* in your mbed_app.json. APN database is by no means exhaustive. It contains a short list of some public
* APNs with publicly available usernames and passwords (if required) in some particular countries only.
* Lookup is done using IMSI (International mobile subscriber identifier).
* Please note that even if 'MBED_CONF_PPP_CELL_IFACE_APN_LOOKUP' config option is set, 'set_credentials()' api still
* gets the precedence. If the aforementioned API is not used and the config option is set but no match is found in
* the lookup table then the driver tries to resort to default APN settings.
*
* Preferred method is to setup APN using 'set_credentials()' API.
* @return 0 on success, negative error code on failure
*/
MBED_DEPRECATED_SINCE("mbed-os-5.9", "This API will be deprecated, use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.")
virtual nsapi_error_t connect();
/** Attempt to disconnect from the network
*
* Brings down the network interface. Shuts down the PPP interface
* of the underlying network stack. Does not bring down the Radio network
*
* @return 0 on success, negative error code on failure
*/
MBED_DEPRECATED_SINCE("mbed-os-5.9", "This API will be deprecated, use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.")
virtual nsapi_error_t disconnect();
/** Adds or removes a SIM facility lock
*
* @deprecated This API will be deprecated in mbed-os-5.9. Use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.
*
* Can be used to enable or disable SIM pin check at device startup.
* This API sets up flags for the driver which would either enable or disable
* SIM pin checking depending upon the user provided argument while establishing
* connection. It doesn't do anything immediately other than setting up flags.
*
* @param set can be set to true if the SIM pin check is supposed to be enabled
* and false if not.
*/
MBED_DEPRECATED_SINCE("mbed-os-5.9", "This API will be deprecated, use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.")
void set_sim_pin_check(bool set);
/** Change the pin for the SIM card
*
* @deprecated This API will be deprecated in mbed-os-5.9. Use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.
*
* Provide the new pin for your SIM card with this API. Old pin code will be assumed to
* be set using set_SIM_pin() API. This API have no immediate effect. While establishing
* connection, driver will change the SIM pin for the next boot.
*
* @param new_pin new pin to be used in string format
*/
MBED_DEPRECATED_SINCE("mbed-os-5.9", "This API will be deprecated, use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.")
void set_new_sim_pin(const char *new_pin);
/** Check if the connection is currently established or not
*
* @deprecated This API will be deprecated in mbed-os-5.9. Use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.
*
* @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.
*/
MBED_DEPRECATED_SINCE("mbed-os-5.9", "This API will be deprecated, use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.")
virtual bool is_connected();
/** Get the local IP address
*
* @deprecated This API will be deprecated in mbed-os-5.9. Use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.
*
* @return Null-terminated representation of the local IP address
* or null if no IP address has been received
*/
MBED_DEPRECATED_SINCE("mbed-os-5.9", "This API will be deprecated, use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.")
virtual const char *get_ip_address();
/** Get the local network mask
*
* @deprecated This API will be deprecated in mbed-os-5.9. Use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.
*
* @return Null-terminated representation of the local network mask
* or null if no network mask has been received
*/
MBED_DEPRECATED_SINCE("mbed-os-5.9", "This API will be deprecated, use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.")
virtual const char *get_netmask();
/** Get the local gateways
*
* @deprecated This API will be deprecated in mbed-os-5.9. Use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.
*
* @return Null-terminated representation of the local gateway
* or null if no network mask has been received
*/
MBED_DEPRECATED_SINCE("mbed-os-5.9", "This API will be deprecated, use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.")
virtual const char *get_gateway();
/** Turn modem debug traces on
*
* @param on set true to enable debug traces
*/
MBED_DEPRECATED_SINCE("mbed-os-5.9", "This API will be deprecated, use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.")
void modem_debug_on(bool on);
/** Register callback for status reporting
*
* @deprecated This API will be deprecated in mbed-os-5.9. Use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.
*
* @param status_cb The callback for status changes
*/
MBED_DEPRECATED_SINCE("mbed-os-5.9", "This API will be deprecated, use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.")
virtual void attach(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb);
/** Get the connection status
*
* @deprecated This API will be deprecated in mbed-os-5.9. Use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.
*
* @return The connection status according to nsapi_connection_status_t
*/
MBED_DEPRECATED_SINCE("mbed-os-5.9", "This API will be deprecated, use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.")
virtual nsapi_connection_status_t get_connection_status() const;
/** Set blocking status of connect() which by default should be blocking
*
* @deprecated This API will be deprecated in mbed-os-5.9. Use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.
*
* @param blocking true if connect is blocking
* @return 0 on success, negative error code on failure
*/
MBED_DEPRECATED_SINCE("mbed-os-5.9", "This API will be deprecated, use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.")
virtual nsapi_error_t set_blocking(bool blocking);
private:
mbed::FileHandle *_fh;
mbed::ATCmdParser *_at;
const char *_new_pin;
const char *_pin;
const char *_apn;
const char *_uname;
const char *_pwd;
bool _debug_trace_on;
nsapi_ip_stack_t _stack;
mbed::Callback<void(nsapi_event_t, intptr_t)> _connection_status_cb;
nsapi_connection_status_t _connect_status;
bool _connect_is_blocking;
void base_initialization();
void setup_at_parser();
void shutdown_at_parser();
nsapi_error_t initialize_sim_card();
nsapi_error_t setup_context_and_credentials();
bool power_up();
void power_down();
void ppp_status_cb(nsapi_event_t, intptr_t);
protected:
/** Enable or disable hang-up detection
*
* When in PPP data pump mode, it is helpful if the FileHandle will signal hang-up via
* POLLHUP, e.g., if the DCD line is deasserted on a UART. During command mode, this
* signaling is not desired. enable_hup() controls whether this function should be
* active.
*
* Meant to be overridden.
*/
virtual void enable_hup(bool enable);
/** Sets the modem up for powering on
*
* modem_init() is equivalent to plugging in the device, e.g., attaching power and serial port.
* It is meant to be overridden.
* If the modem is on-board, an implementation of onboard_modem_api.h
* will override this.
* If the the modem is a plugged-in device (i.e., a shield type component), the driver deriving from this
* class will override.
*/
virtual void modem_init();
/** Sets the modem in unplugged state
*
* modem_deinit() will be equivalent to pulling the plug off of the device, i.e., detaching power
* and serial port. This puts the modem in lowest power state.
* It is meant to be overridden.
* If the modem is on-board, an implementation of onboard_modem_api.h
* will override this.
* If the the modem is a plugged-in device (i.e., a shield type component), the driver deriving from this
* class will override.
*/
virtual void modem_deinit();
/** Powers up the modem
*
* modem_power_up() is equivalent to pressing the soft power button.
* The driver may repeat this if the modem is not responsive to AT commands.
* It is meant to be overridden.
* If the modem is on-board, an implementation of onboard_modem_api.h
* will override this.
* If the the modem is a plugged-in device (i.e., a shield type component), the driver deriving from this
* class will override.
*/
virtual void modem_power_up();
/** Powers down the modem
*
* modem_power_down() is equivalent to turning off the modem by button press.
* It is meant to be overridden.
* If the modem is on-board, an implementation of onboard_modem_api.h
* will override this.
* If the the modem is a plugged-in device (i.e., a shield type component), the driver deriving from this
* class will override.
*/
virtual void modem_power_down();
/** Provide access to the underlying stack
*
* @return The underlying network stack
*/
virtual NetworkStack *get_stack();
/** Starts network registration process.
*
* Potential users could be subclasses who are not network interface
* but would like to use CellularBase infrastructure to register
* with a cellular network, e.g., an SMS extension to CellularBase.
*
* @param nwk_type type of network to connect, defaults to packet switched network
*
* @return true if registration is successful
*/
bool nwk_registration(uint8_t nwk_type = PACKET_SWITCHED);
};
#endif //NSAPI_PPP_AVAILABLE
#endif //PPP_CELLULAR_INTERFACE_

View File

@ -1,69 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2017 ARM Limited
*
* 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 MBED_OS_GMD_UT_CONFIG_HEADER_H_
#define MBED_OS_GMD_UT_CONFIG_HEADER_H_
// The number of retries for UDP exchanges
#define NUM_UDP_RETRIES 5
// How long to wait for stuff to travel in the async echo tests
#define ASYNC_TEST_WAIT_TIME 10000
#define TEST_DATA "_____0000:0123456789012345678901234567890123456789" \
"01234567890123456789012345678901234567890123456789" \
"_____0100:0123456789012345678901234567890123456789" \
"01234567890123456789012345678901234567890123456789" \
"_____0200:0123456789012345678901234567890123456789" \
"01234567890123456789012345678901234567890123456789" \
"_____0300:0123456789012345678901234567890123456789" \
"01234567890123456789012345678901234567890123456789" \
"_____0400:0123456789012345678901234567890123456789" \
"01234567890123456789012345678901234567890123456789" \
"_____0500:0123456789012345678901234567890123456789" \
"01234567890123456789012345678901234567890123456789" \
"_____0600:0123456789012345678901234567890123456789" \
"01234567890123456789012345678901234567890123456789" \
"_____0700:0123456789012345678901234567890123456789" \
"01234567890123456789012345678901234567890123456789" \
"_____0800:0123456789012345678901234567890123456789" \
"01234567890123456789012345678901234567890123456789" \
"_____0900:0123456789012345678901234567890123456789" \
"01234567890123456789012345678901234567890123456789" \
"_____1000:0123456789012345678901234567890123456789" \
"01234567890123456789012345678901234567890123456789" \
"_____1100:0123456789012345678901234567890123456789" \
"01234567890123456789012345678901234567890123456789" \
"_____1200:0123456789012345678901234567890123456789" \
"01234567890123456789012345678901234567890123456789" \
"_____1300:0123456789012345678901234567890123456789" \
"01234567890123456789012345678901234567890123456789" \
"_____1400:0123456789012345678901234567890123456789" \
"01234567890123456789012345678901234567890123456789" \
"_____1500:0123456789012345678901234567890123456789" \
"01234567890123456789012345678901234567890123456789" \
"_____1600:0123456789012345678901234567890123456789" \
"01234567890123456789012345678901234567890123456789" \
"_____1700:0123456789012345678901234567890123456789" \
"01234567890123456789012345678901234567890123456789" \
"_____1800:0123456789012345678901234567890123456789" \
"01234567890123456789012345678901234567890123456789" \
"_____1900:0123456789012345678901234567890123456789" \
"01234567890123456789012345678901234567890123456789" \
"_____2000:0123456789012345678901234567890123456789" \
"01234567890123456789012345678901234567890123456789";
#endif /* MBED_OS_GMD_UT_CONFIG_HEADER_H_ */

View File

@ -1,435 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2017 ARM Limited
*
* 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.
*/
#if !MODEM_ON_BOARD
#error [NOT_SUPPORTED] MODEM_ON_BOARD should be set for this test to be functional
#endif
#include "mbed.h"
#include "gmd_ut_config_header.h"
#include "greentea-client/test_env.h"
#include "unity.h"
#include "utest.h"
//Add your driver's header file here
#include "OnboardCellularInterface.h"
#include "UDPSocket.h"
#include "TCPSocket.h"
#include "mbed_trace.h"
#define TRACE_GROUP "TEST"
using namespace utest::v1;
#if !defined(MBED_CONF_APP_DEFAULT_PIN)
#error [NOT_SUPPORTED] A json configuration file is needed. Skipping this build.
#endif
/** How to run port verification tests
*
* i) Copy this file in your implementation directory
* e.g., netsocket/cellular/YOUR_IMPLEMENTATION/TESTS/unit_tests/default/
* ii) Rename OnboardCellularInterface everywhere in this file with your Class
* iii) Make an empty test application with the fork of mbed-os where your implementation resides
* iv) Create a json file in the root directory of your application and copy the contents of
* template_mbed_app.txt into it
* v) Now from the root of your application, enter this command:
* mbed test --compile-list
* Look for the name of of your test suite matching to the directory path
* vi) Run tests with the command:
* mbed test -n YOUR_TEST_SUITE_NAME
*
* For more information on mbed-greentea testing suite, please visit:
* https://docs.mbed.com/docs/mbed-os-handbook/en/latest/advanced/greentea/
*/
// Lock for debug prints
static Mutex mtx;
// An instance of the cellular driver
// change this with the name of your driver
static OnboardCellularInterface driver(true);
// Test data
static const char test_data[] = TEST_DATA;
//Private Function prototypes
static nsapi_error_t do_connect(OnboardCellularInterface *iface);
static int fix(int size, int limit);
static void do_udp_echo(UDPSocket *sock, SocketAddress *host_address, int size);
static int send_all(TCPSocket *sock, const char *data, int size);
static void async_cb(bool *callback_triggered);
static void do_tcp_echo_async(TCPSocket *sock, int size, bool *callback_triggered);
static void use_connection(OnboardCellularInterface *driver);
static void drop_connection(OnboardCellularInterface *driver);
static void lock();
static void unlock();
/*
* Verification tests for a successful porting
* These tests must pass:
*
* test_udp_echo()
* test_tcp_echo_async
* test_connect_credentials
* test_connect_preset_credentials
*/
/**
* Test UDP data exchange
*/
void test_udp_echo()
{
UDPSocket sock;
SocketAddress host_address;
int x;
int size;
driver.disconnect();
TEST_ASSERT(do_connect(&driver) == 0);
TEST_ASSERT(driver.gethostbyname(MBED_CONF_APP_ECHO_SERVER, &host_address) == 0);
host_address.set_port(MBED_CONF_APP_ECHO_UDP_PORT);
tr_debug("UDP: Server %s address: %s on port %d.",
MBED_CONF_APP_ECHO_SERVER, host_address.get_ip_address(),
host_address.get_port());
TEST_ASSERT(sock.open(&driver) == 0)
sock.set_timeout(10000);
// Test min, max, and some random sizes in-between
do_udp_echo(&sock, &host_address, 1);
do_udp_echo(&sock, &host_address, MBED_CONF_APP_UDP_MAX_PACKET_SIZE);
for (x = 0; x < 10; x++) {
size = (rand() % MBED_CONF_APP_UDP_MAX_PACKET_SIZE) + 1;
size = fix(size, MBED_CONF_APP_UDP_MAX_PACKET_SIZE + 1);
do_udp_echo(&sock, &host_address, size);
}
sock.close();
drop_connection(&driver);
tr_debug("%d UDP packets of size up to %d byte(s) echoed successfully.", x,
MBED_CONF_APP_UDP_MAX_PACKET_SIZE);
}
/**
* Test TCP data exchange via the asynchronous sigio() mechanism
*/
void test_tcp_echo_async()
{
TCPSocket sock;
SocketAddress host_address;
bool callback_triggered = false;
int x;
int size;
driver.disconnect();
TEST_ASSERT(do_connect(&driver) == 0);
TEST_ASSERT(
driver.gethostbyname(MBED_CONF_APP_ECHO_SERVER, &host_address) == 0);
host_address.set_port(MBED_CONF_APP_ECHO_TCP_PORT);
tr_debug("TCP: Server %s address: %s on port %d.",
MBED_CONF_APP_ECHO_SERVER, host_address.get_ip_address(),
host_address.get_port());
TEST_ASSERT(sock.open(&driver) == 0)
// Set up the async callback and set the timeout to zero
sock.sigio(callback(async_cb, &callback_triggered));
sock.set_timeout(0);
TEST_ASSERT(sock.connect(host_address) == 0);
// Test min, max, and some random sizes in-between
do_tcp_echo_async(&sock, 1, &callback_triggered);
do_tcp_echo_async(&sock, MBED_CONF_APP_TCP_MAX_PACKET_SIZE,
&callback_triggered);
sock.close();
drop_connection(&driver);
tr_debug("TCP packets of size up to %d byte(s) echoed asynchronously and successfully.",
MBED_CONF_APP_TCP_MAX_PACKET_SIZE);
}
/**
* Connect with credentials included in the connect request
*/
void test_connect_credentials()
{
driver.disconnect();
TEST_ASSERT(do_connect(&driver) == 0);
use_connection(&driver);
drop_connection(&driver);
}
/**
* Test with credentials preset
*/
void test_connect_preset_credentials()
{
driver.disconnect();
driver.set_sim_pin(MBED_CONF_APP_DEFAULT_PIN);
driver.set_credentials(MBED_CONF_APP_APN, MBED_CONF_APP_USERNAME,
MBED_CONF_APP_PASSWORD);
int num_retries = 0;
nsapi_error_t err = NSAPI_ERROR_OK;
while (!driver.is_connected()) {
err = driver.connect();
if (err == NSAPI_ERROR_OK || num_retries > MBED_CONF_APP_MAX_RETRIES) {
break;
}
}
TEST_ASSERT(err == 0);
use_connection(&driver);
drop_connection(&driver);
}
/**
* Setup Test Environment
*/
utest::v1::status_t test_setup(const size_t number_of_cases)
{
// Setup Greentea with a timeout
GREENTEA_SETUP(600, "default_auto");
return verbose_test_setup_handler(number_of_cases);
}
/**
* Array defining test cases
*/
Case cases[] = { Case("UDP echo test", test_udp_echo),
#if MBED_CONF_LWIP_TCP_ENABLED
Case("TCP async echo test", test_tcp_echo_async),
#endif
Case("Connect with credentials", test_connect_credentials),
Case("Connect with preset credentials", test_connect_preset_credentials)
};
Specification specification(test_setup, cases);
/**
* main test harness
*/
int main()
{
mbed_trace_init();
mbed_trace_mutex_wait_function_set(lock);
mbed_trace_mutex_release_function_set(unlock);
// Run tests
return !Harness::run(specification);
}
/**
* connect to the network
*/
static nsapi_error_t do_connect(OnboardCellularInterface *iface)
{
int num_retries = 0;
nsapi_error_t err = NSAPI_ERROR_OK;
while (!iface->is_connected()) {
err = driver.connect(MBED_CONF_APP_DEFAULT_PIN, MBED_CONF_APP_APN,
MBED_CONF_APP_USERNAME, MBED_CONF_APP_PASSWORD);
if (err == NSAPI_ERROR_OK || num_retries > MBED_CONF_APP_MAX_RETRIES) {
break;
}
num_retries++;
}
return err;
}
/**
* Get a random size for the test packet
*/
static int fix(int size, int limit)
{
if (size <= 0) {
size = limit / 2;
} else if (size > limit) {
size = limit;
}
return size;
}
/**
* Do a UDP socket echo test to a given host of a given packet size
*/
static void do_udp_echo(UDPSocket *sock, SocketAddress *host_address, int size)
{
bool success = false;
void *recv_data = malloc(size);
TEST_ASSERT(recv_data != NULL);
// Retry this a few times, don't want to fail due to a flaky link
for (int x = 0; !success && (x < NUM_UDP_RETRIES); x++) {
tr_debug("Echo testing UDP packet size %d byte(s), try %d.", size, x + 1);
if ((sock->sendto(*host_address, (void *) test_data, size) == size)
&& (sock->recvfrom(host_address, recv_data, size) == size)) {
TEST_ASSERT(memcmp(test_data, recv_data, size) == 0);
success = true;
}
}
TEST_ASSERT(success);
free(recv_data);
}
/**
* Send an entire TCP data buffer until done
*/
static int send_all(TCPSocket *sock, const char *data, int size)
{
int x;
int count = 0;
Timer timer;
timer.start();
while ((count < size) && (timer.read_ms() < ASYNC_TEST_WAIT_TIME)) {
x = sock->send(data + count, size - count);
if (x > 0) {
count += x;
tr_debug("%d byte(s) sent, %d left to send.", count, size - count);
}
wait_ms(10);
}
timer.stop();
return count;
}
/**
* The asynchronous callback
*/
static void async_cb(bool *callback_triggered)
{
TEST_ASSERT(callback_triggered != NULL);
*callback_triggered = true;
}
/**
* Do a TCP echo using the asynchronous driver
*/
static void do_tcp_echo_async(TCPSocket *sock, int size,
bool *callback_triggered)
{
void *recv_data = malloc(size);
int recv_size = 0;
int remaining_size;
int x, y;
Timer timer;
TEST_ASSERT(recv_data != NULL);
*callback_triggered = false;
tr_debug("Echo testing TCP packet size %d byte(s) async.", size);
TEST_ASSERT(send_all(sock, test_data, size) == size);
// Wait for all the echoed data to arrive
timer.start();
remaining_size = size;
while ((recv_size < size) && (timer.read_ms() < ASYNC_TEST_WAIT_TIME)) {
if (*callback_triggered) {
*callback_triggered = false;
x = sock->recv((char *) recv_data + recv_size, remaining_size);
if (x > 0) {
recv_size += x;
remaining_size = size - recv_size;
tr_debug("%d byte(s) echoed back so far, %d to go.", recv_size,
remaining_size);
}
}
wait_ms(10);
}
TEST_ASSERT(recv_size == size);
y = memcmp(test_data, recv_data, size);
if (y != 0) {
tr_debug("Sent %d, |%*.*s|", size, size, size, test_data);
tr_debug("Rcvd %d, |%*.*s|", size, size, size, (char *) recv_data);
// We do not assert a failure here because ublox TCP echo server doesn't send
// back original data. It actually constructs a ublox message string. They need to fix it as
// at the minute in case of TCP, their server is not behaving like a echo TCP server.
//TEST_ASSERT(false);
}
timer.stop();
free(recv_data);
}
/**
* Use a connection, checking that it is good
* Checks via doing an NTP transaction
*/
static void use_connection(OnboardCellularInterface *driver)
{
const char *ip_address = driver->get_ip_address();
const char *net_mask = driver->get_netmask();
const char *gateway = driver->get_gateway();
TEST_ASSERT(driver->is_connected());
TEST_ASSERT(ip_address != NULL);
tr_debug("IP address %s.", ip_address);
TEST_ASSERT(net_mask != NULL);
tr_debug("Net mask %s.", net_mask);
TEST_ASSERT(gateway != NULL);
tr_debug("Gateway %s.", gateway);
UDPSocket sock;
SocketAddress host_address;
TEST_ASSERT(driver->gethostbyname(MBED_CONF_APP_ECHO_SERVER, &host_address) == 0);
host_address.set_port(MBED_CONF_APP_ECHO_UDP_PORT);
tr_debug("UDP: Server %s address: %s on port %d.",
MBED_CONF_APP_ECHO_SERVER, host_address.get_ip_address(),
host_address.get_port());
TEST_ASSERT(sock.open(driver) == 0)
sock.set_timeout(10000);
do_udp_echo(&sock, &host_address, 1);
sock.close();
}
/**
* Drop a connection and check that it has dropped
*/
static void drop_connection(OnboardCellularInterface *driver)
{
TEST_ASSERT(driver->disconnect() == 0);
TEST_ASSERT(!driver->is_connected());
}
/**
* Locks for debug prints
*/
static void lock()
{
mtx.lock();
}
static void unlock()
{
mtx.unlock();
}

View File

@ -1,68 +0,0 @@
{
"config": {
"platform": {
"help": "The platform for the cellular feature, e.g. UBLOX or MTS_DRAGONFLY",
"value": "UBLOX"
},
"max-retries": {
"help": "Network can be intermittent, number of retries before giving up",
"value": 3
},
"default-pin": {
"help": "The current value of the SIM PIN as a string",
"value": "\"1234\""
},
"apn": {
"help": "The APN string to use for this SIM/network, set to 0 if none",
"value": "\"internet\""
},
"username": {
"help": "The user name string to use for this APN, set to zero if none",
"value": 0
},
"password": {
"help": "The password string to use for this APN, set to 0 if none",
"value": 0
},
"echo-server": {
"help": "The URL string of the UDP/TCP echo server to use during testing",
"value": "\"echo.u-blox.com\""
},
"echo-udp-port": {
"help": "The port to connect to on echo-server for UDP testing",
"value": 7
},
"echo-tcp-port": {
"help": "The port to connect to on echo-server for TCP testing",
"value": 7
},
"ntp-server": {
"help": "The URL string of the NTP server to use during testing",
"value": "\"2.pool.ntp.org\""
},
"ntp-port": {
"help": "The port to connect to on ntp-server",
"value": 123
},
"udp-max-packet-size": {
"help": "The maximum UDP packet size to use",
"value": 508
},
"tcp-max-packet-size": {
"help": "The maximum TCP packet size to use",
"value": 1500
}
},
"target_overrides": {
"*": {
"lwip.ipv4-enabled": true,
"lwip.ethernet-enabled": false,
"lwip.ppp-enabled": true,
"lwip.tcp-enabled": true,
"platform.stdio-convert-newlines": true,
"platform.stdio-baud-rate": 115200,
"platform.default-serial-baud-rate": 115200,
"mbed-trace.enable": 1
}
}
}

View File

@ -1,39 +0,0 @@
/* Copyright (c) 2017 ARM Limited
*
* 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 "UARTCellularInterface.h"
#if NSAPI_PPP_AVAILABLE
UARTCellularInterface::UARTCellularInterface(PinName txd, PinName rxd, PinName dcd, PinName rts, PinName cts, PinName ri,
PinName dtr, PinName dsr, int baud, bool active_high, bool debug) :
PPPCellularInterface(&_serial, debug),
_serial(txd, rxd, baud)
{
_dcd_pin = dcd;
_active_high = active_high;
}
UARTCellularInterface::~UARTCellularInterface()
{
//do nothing
}
void UARTCellularInterface::enable_hup(bool enable)
{
_serial.set_data_carrier_detect(enable ? _dcd_pin : NC, _active_high);
}
#endif // NSAPI_PPP_AVAILABLE

View File

@ -1,77 +0,0 @@
/* Copyright (c) 2017 ARM Limited
*
* 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 UART_CELLULAR_INTERFACE_
#define UART_CELLULAR_INTERFACE_
#include "PPPCellularInterface.h"
#include "UARTSerial.h"
#if NSAPI_PPP_AVAILABLE
/** UARTCellularInterface class
*
* @deprecated This API will be deprecated in mbed-os-5.9. Use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.
*
* This interface serves as the controller/driver for Cellular
* modems attached via a UART (tested with UBLOX_C027 and MTS_DRAGONFLY_F411RE).
*
* It constructs a FileHandle and passes it back to its base class as well as overrides
* enable_hup() in the base class.
*/
class UARTCellularInterface : public PPPCellularInterface {
public:
/** Constructor
*
* @deprecated This API will be deprecated in mbed-os-5.9. Use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.
*/
MBED_DEPRECATED_SINCE("mbed-os-5.9", "This API will be deprecated, use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.")
UARTCellularInterface(PinName tx, PinName rx, PinName dcd = NC, PinName rts = NC, PinName cts = NC, PinName ri = NC,
PinName dtr = NC, PinName dsr = NC, int baud = MBED_CONF_PPP_CELL_IFACE_BAUD_RATE,
bool active_high = false,
bool debug = false);
/** Destructor
*
* @deprecated This API will be deprecated in mbed-os-5.9. Use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.
*/
MBED_DEPRECATED_SINCE("mbed-os-5.9", "This API will be deprecated, use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.")
virtual ~UARTCellularInterface();
private:
mbed::UARTSerial _serial;
PinName _dcd_pin;
bool _active_high;
protected:
/** Enable or disable hang-up detection
*
* @deprecated This API will be deprecated in mbed-os-5.9. Use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.
*
* When in PPP data pump mode, it is helpful if the FileHandle will signal hang-up via
* POLLHUP, e.g., if the DCD line is deasserted on a UART. During command mode, this
* signaling is not desired. enable_hup() controls whether this function should be
* active.
*/
MBED_DEPRECATED_SINCE("mbed-os-5.9", "This API will be deprecated, use mbed-os/features/cellular/easy_cellular/EasyCellularConnection.h instead.")
virtual void enable_hup(bool enable);
};
#endif //NSAPI_PPP_AVAILABLE
#endif //UART_CELLULAR_INTERFACE_