mirror of https://github.com/ARMmbed/mbed-os.git
Initial cellular feature
parent
a137444754
commit
863ec3c3cc
|
@ -0,0 +1,513 @@
|
|||
/*
|
||||
* Copyright (c) 2017, 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 <mbed.h>
|
||||
|
||||
|
||||
#include "CellularConnectionUtil.h"
|
||||
|
||||
#ifndef MBED_TRACE_MAX_LEVEL
|
||||
#define MBED_TRACE_MAX_LEVEL TRACE_LEVEL_INFO
|
||||
#endif
|
||||
#include "CellularLog.h"
|
||||
/*#define log_debug printf
|
||||
#define log_info printf
|
||||
#define log_warn printf
|
||||
#define log_error printf
|
||||
*/
|
||||
|
||||
// timeout to wait for AT responses
|
||||
#define TIMEOUT_POWER_ON (1*1000)
|
||||
#define TIMEOUT_SIM_PIN (1*1000)
|
||||
#define TIMEOUT_NETWORK (10*1000)
|
||||
#define TIMEOUT_REGISTRATION (180*1000)
|
||||
|
||||
static EventQueue at_queue(8 * EVENTS_EVENT_SIZE);
|
||||
static CELLULAR_DEVICE cellularDevice(at_queue);
|
||||
|
||||
#define ENUM_MACRO(name, v1, v2, v3, v4, v5, v6, v7)\
|
||||
enum name { v1, v2, v3, v4, v5, v6, v7};\
|
||||
const char *name##Strings[] = { #v1, #v2, #v3, #v4, #v5, #v6, #v7};
|
||||
|
||||
CellularConnectionUtil::CellularConnectionUtil() : _serial(0), _state(STATE_POWER_ON), _next_state(_state), _status_callback(0), _network(0), _power(0), _queue(8 * EVENTS_EVENT_SIZE), _queue_thread(0), _cellularDevice(&cellularDevice)
|
||||
{
|
||||
}
|
||||
|
||||
CellularConnectionUtil::~CellularConnectionUtil()
|
||||
{
|
||||
stop();
|
||||
}
|
||||
|
||||
bool CellularConnectionUtil::open_power(FileHandle *fh)
|
||||
{
|
||||
if (!_power) {
|
||||
_power = _cellularDevice->open_power(fh);
|
||||
if (!_power) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
nsapi_error_t err = _power->on();
|
||||
if (err != NSAPI_ERROR_OK && err != NSAPI_ERROR_UNSUPPORTED) {
|
||||
log_warn("Cellular start failed. Power off/on.");
|
||||
err = _power->off();
|
||||
if (err != NSAPI_ERROR_OK && err != NSAPI_ERROR_UNSUPPORTED) {
|
||||
log_error("Cellular power down failed!");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CellularConnectionUtil::open_sim()
|
||||
{
|
||||
#ifdef MBED_CONF_APP_CELLULAR_SIM_PIN
|
||||
nsapi_error_t err;
|
||||
static CellularSIM *sim;
|
||||
if (!sim) {
|
||||
sim = _cellularDevice->open_sim(_serial);
|
||||
}
|
||||
if (!sim) {
|
||||
return false;
|
||||
}
|
||||
CellularSIM::SimState state = CellularSIM::SimStateUnknown;
|
||||
// wait until SIM is readable
|
||||
// here you could add wait(secs) if you know start delay of your SIM
|
||||
while (sim->get_sim_state(state) != NSAPI_ERROR_OK || state == CellularSIM::SimStateUnknown) {
|
||||
log_debug("Waiting for SIM (state %d)...", state);
|
||||
return false;
|
||||
}
|
||||
if (state == CellularSIM::SimStatePinNeeded) {
|
||||
log_info("SIM pin required, entering pin: %s", MBED_CONF_APP_CELLULAR_SIM_PIN);
|
||||
err = sim->set_pin(MBED_CONF_APP_CELLULAR_SIM_PIN);
|
||||
if (err) {
|
||||
log_error("SIM pin set failed with: %d, bailing out...", err);
|
||||
return false;
|
||||
}
|
||||
// here you could add wait(secs) if you know delay of changing PIN on your SIM
|
||||
for (int i = 0; i < MAX_SIM_READY_WAITING_TIME; i++) {
|
||||
if (sim->get_sim_state(state) == NSAPI_ERROR_OK && state == CellularSIM::SimStateReady) {
|
||||
break;
|
||||
}
|
||||
log_debug("SIM state: %d", state);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return state == CellularSIM::SimStateReady;
|
||||
#else
|
||||
log_info("Continue without SIM.");
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool CellularConnectionUtil::run_self_tests()
|
||||
{
|
||||
CellularInformation *info = _cellularDevice->open_information(_serial);
|
||||
|
||||
char buf[2048];
|
||||
if (info->get_manufacturer(buf, sizeof(buf)) == NSAPI_ERROR_OK) {
|
||||
log_info("Cellular device manufacturer: %s", buf);
|
||||
}
|
||||
if (info->get_model(buf, sizeof(buf)) == NSAPI_ERROR_OK) {
|
||||
log_info("Cellular device model: %s", buf);
|
||||
}
|
||||
if (info->get_revision(buf, sizeof(buf)) == NSAPI_ERROR_OK) {
|
||||
log_info("Cellular device revision: %s", buf);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CellularConnectionUtil::open_network()
|
||||
{
|
||||
if (!_network) {
|
||||
_network = _cellularDevice->open_network(_serial);
|
||||
}
|
||||
return (_network != NULL);
|
||||
}
|
||||
|
||||
bool CellularConnectionUtil::set_network_registration(char *plmn)
|
||||
{
|
||||
if (_network->set_registration(plmn) != NSAPI_ERROR_OK) {
|
||||
log_error("Failed to set network registration.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CellularConnectionUtil::get_network_registration(CellularNetwork::RegistrationType type, CellularNetwork::RegistrationStatus &status, bool &is_registered)
|
||||
{
|
||||
is_registered = false;
|
||||
bool is_roaming = false;
|
||||
if (_network->get_registration_status(type, status) != NSAPI_ERROR_OK) {
|
||||
return false;
|
||||
}
|
||||
switch (status) {
|
||||
case CellularNetwork::RegisteredRoaming:
|
||||
is_roaming = true;
|
||||
// fall-through
|
||||
case CellularNetwork::RegisteredHomeNetwork:
|
||||
is_registered = true;
|
||||
break;
|
||||
case CellularNetwork::RegisteredSMSOnlyRoaming:
|
||||
is_roaming = true;
|
||||
// fall-through
|
||||
case CellularNetwork::RegisteredSMSOnlyHome:
|
||||
log_warn("SMS only network registration!");
|
||||
is_registered = true;
|
||||
break;
|
||||
case CellularNetwork::RegisteredCSFBNotPreferredRoaming:
|
||||
is_roaming = true;
|
||||
// fall-through
|
||||
case CellularNetwork::RegisteredCSFBNotPreferredHome:
|
||||
log_warn("Not preferred network registration!");
|
||||
is_registered = true;
|
||||
break;
|
||||
case CellularNetwork::AttachedEmergencyOnly:
|
||||
case CellularNetwork::RegistrationDenied:
|
||||
case CellularNetwork::NotRegistered:
|
||||
case CellularNetwork::Unknown:
|
||||
case CellularNetwork::SearchingNetwork:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_roaming) {
|
||||
log_warn("Roaming cellular network!");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CellularConnectionUtil::get_attach_network(CellularNetwork::AttachStatus &status)
|
||||
{
|
||||
nsapi_error_t err = _network->get_attach(status);
|
||||
if (err != NSAPI_ERROR_OK) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CellularConnectionUtil::set_attach_network()
|
||||
{
|
||||
nsapi_error_t attach_err = _network->set_attach();
|
||||
if (attach_err != NSAPI_ERROR_OK) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void CellularConnectionUtil::report_failure(const char* msg)
|
||||
{
|
||||
log_error("Cellular network failed: %s", msg);
|
||||
if (_status_callback) {
|
||||
_status_callback(_state, _next_state);
|
||||
}
|
||||
}
|
||||
|
||||
bool CellularConnectionUtil::continue_with_state(CellularState state)
|
||||
{
|
||||
_state = state;
|
||||
if (!_queue.call_in(0, callback(this, &CellularConnectionUtil::event))) {
|
||||
stop();
|
||||
return NSAPI_ERROR_NO_MEMORY;
|
||||
}
|
||||
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
void CellularConnectionUtil::event()
|
||||
{
|
||||
nsapi_error_t err;
|
||||
int event_timeout = -1;
|
||||
switch (_state) {
|
||||
case STATE_POWER_ON:
|
||||
cellularDevice.set_timeout(TIMEOUT_POWER_ON);
|
||||
log_info("Cellular power ON (timeout %d ms)", TIMEOUT_POWER_ON);
|
||||
if (open_power(_serial)) {
|
||||
_next_state = STATE_SELF_TEST;
|
||||
} else {
|
||||
static int retry_count;
|
||||
if (++retry_count < 10) {
|
||||
log_warn("Power ON retry %d", retry_count);
|
||||
event_timeout = 1000;
|
||||
} else {
|
||||
report_failure("Power");
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case STATE_SELF_TEST:
|
||||
cellularDevice.set_timeout(TIMEOUT_POWER_ON);
|
||||
log_info("Cellular self-test (timeout %d ms)", TIMEOUT_POWER_ON);
|
||||
if (_power->set_at_mode() == NSAPI_ERROR_OK) {
|
||||
_next_state = STATE_START_CELLULAR;
|
||||
run_self_tests();
|
||||
} else {
|
||||
static int retry_count = 0;
|
||||
if (++retry_count < 10) {
|
||||
log_warn("Waiting for cellular %d", retry_count);
|
||||
event_timeout = 1000;
|
||||
} else {
|
||||
report_failure("Power");
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case STATE_START_CELLULAR:
|
||||
cellularDevice.set_timeout(TIMEOUT_NETWORK);
|
||||
log_info("Start cellular (timeout %d ms)", TIMEOUT_NETWORK);
|
||||
open_network();
|
||||
_next_state = STATE_SIM_PIN;
|
||||
break;
|
||||
case STATE_SIM_PIN:
|
||||
cellularDevice.set_timeout(TIMEOUT_SIM_PIN);
|
||||
log_info("Start cellular (timeout %d ms)", TIMEOUT_SIM_PIN);
|
||||
if (open_sim()) {
|
||||
_next_state = STATE_REGISTERING_NETWORK;
|
||||
log_info("Check for network registration");
|
||||
} else {
|
||||
static int retry_count;
|
||||
if (++retry_count < 10) {
|
||||
log_warn("Waiting for SIM %d", retry_count);
|
||||
event_timeout = 1000;
|
||||
} else {
|
||||
report_failure("Entering SIM PIN");
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case STATE_REGISTERING_NETWORK:
|
||||
cellularDevice.set_timeout(TIMEOUT_NETWORK);
|
||||
CellularNetwork::RegistrationStatus status;
|
||||
bool is_registered;
|
||||
for (int type = 0; type < CellularNetwork::C_MAX; type++) {
|
||||
if (get_network_registration((CellularNetwork::RegistrationType)type, status, is_registered)) {
|
||||
if (is_registered) {
|
||||
log_info("Registered to cellular network (status %d)", status);
|
||||
_next_state = STATE_ATTACH_NETWORK;
|
||||
log_info("Check cellular network attach state");
|
||||
event_timeout = 0;
|
||||
break;
|
||||
} else {
|
||||
if (status == CellularNetwork::RegistrationDenied) {
|
||||
static int backoff_timeout = 1;
|
||||
log_warn("Network registration denied! Retry after %d seconds.", backoff_timeout);
|
||||
event_timeout = backoff_timeout * 1000;
|
||||
backoff_timeout *= 2;
|
||||
_next_state = STATE_REGISTERING_NETWORK;
|
||||
break;
|
||||
} else if (status == CellularNetwork::NotRegistered) {
|
||||
log_info("(STATE_REGISTERING_NETWORK), not registered");
|
||||
if (event_timeout == -1) {
|
||||
_next_state = STATE_REGISTER_NETWORK;
|
||||
event_timeout = 0;
|
||||
}
|
||||
} else {
|
||||
static int retry_count;
|
||||
if (++retry_count < 18) {
|
||||
log_info("Waiting for registration");
|
||||
event_timeout = 1*1000;
|
||||
_next_state = STATE_REGISTERING_NETWORK;
|
||||
} else {
|
||||
if (event_timeout == -1) {
|
||||
log_info("Start cellular registration");
|
||||
_next_state = STATE_REGISTER_NETWORK;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_state == _next_state && event_timeout == -1) {
|
||||
event_timeout = 0;
|
||||
}
|
||||
break;
|
||||
case STATE_REGISTER_NETWORK:
|
||||
cellularDevice.set_timeout(TIMEOUT_REGISTRATION);
|
||||
log_info("Register to cellular network (timeout %d ms)", TIMEOUT_REGISTRATION);
|
||||
if (set_network_registration()) {
|
||||
_next_state = STATE_REGISTERING_NETWORK;
|
||||
} else {
|
||||
static int retry_count;
|
||||
if (++retry_count < 3) {
|
||||
event_timeout = 1000;
|
||||
} else {
|
||||
report_failure("Registration");
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case STATE_ATTACHING_NETWORK:
|
||||
cellularDevice.set_timeout(TIMEOUT_NETWORK);
|
||||
CellularNetwork::AttachStatus attach_status;
|
||||
if (get_attach_network(attach_status)) {
|
||||
if (attach_status == CellularNetwork::Attached) {
|
||||
_next_state = STATE_CONNECT_NETWORK;
|
||||
} else {
|
||||
_next_state = STATE_ATTACH_NETWORK;
|
||||
}
|
||||
} else {
|
||||
event_timeout = 0;
|
||||
}
|
||||
break;
|
||||
case STATE_ATTACH_NETWORK:
|
||||
cellularDevice.set_timeout(TIMEOUT_NETWORK);
|
||||
log_info("Attach to cellular network (timeout %d ms)", TIMEOUT_NETWORK);
|
||||
if (set_attach_network()) {
|
||||
_next_state = STATE_ATTACHING_NETWORK;
|
||||
log_info("Cellular network attaching");
|
||||
} else {
|
||||
event_timeout = 0;
|
||||
}
|
||||
break;
|
||||
case STATE_CONNECT_NETWORK:
|
||||
cellularDevice.set_timeout(TIMEOUT_NETWORK);
|
||||
log_info("Connect to cellular network (timeout %d ms)", TIMEOUT_NETWORK);
|
||||
// Set APN
|
||||
//network->set_credentials("internet");
|
||||
err = _network->connect();
|
||||
if (!err) {
|
||||
_next_state = STATE_READY;
|
||||
} else {
|
||||
report_failure("Network connect");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case STATE_READY:
|
||||
cellularDevice.set_timeout(TIMEOUT_NETWORK);
|
||||
log_debug("Cellular ready! (timeout %d ms)", TIMEOUT_NETWORK);
|
||||
if (_status_callback) {
|
||||
_status_callback(_state, _next_state);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
MBED_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
|
||||
if (_next_state != _state || event_timeout >= 0) {
|
||||
if (_next_state != _state) {
|
||||
log_info("Cellular state from %d to %d", _state, _next_state);
|
||||
if (_status_callback) {
|
||||
if (!_status_callback(_state, _next_state)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (event_timeout == 0) {
|
||||
static int retry_count = 0;
|
||||
if (++retry_count < 3) {
|
||||
log_info("Cellular event retry %d", retry_count);
|
||||
} else {
|
||||
report_failure("Cellular connection failed!");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
log_info("Cellular event in %d milliseconds", event_timeout);
|
||||
}
|
||||
}
|
||||
_state = _next_state;
|
||||
if (event_timeout == -1) {
|
||||
event_timeout = 0;
|
||||
}
|
||||
if (!_queue.call_in(event_timeout, callback(this, &CellularConnectionUtil::event))) {
|
||||
report_failure("Cellular event failure!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CellularConnectionUtil::start(bool start_dispatch)
|
||||
{
|
||||
log_info("CellularConnectionUtil::start");
|
||||
_power = _cellularDevice->open_power(_serial);
|
||||
if (!_power) {
|
||||
stop();
|
||||
return false;
|
||||
}
|
||||
_network = _cellularDevice->open_network(_serial);
|
||||
if (!_network) {
|
||||
stop();
|
||||
return false;
|
||||
}
|
||||
if (!_queue.call_in(0, callback(this, &CellularConnectionUtil::event))) {
|
||||
stop();
|
||||
return false;
|
||||
}
|
||||
|
||||
at_queue.chain(&_queue);
|
||||
|
||||
if (start_dispatch) {
|
||||
log_info("Create cellular thread");
|
||||
_queue_thread = new Thread();
|
||||
if (!_queue_thread) {
|
||||
stop();
|
||||
return false;
|
||||
}
|
||||
if (_queue_thread->start(callback(&_queue, &EventQueue::dispatch_forever)) != osOK) {
|
||||
stop();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
log_info("CellularConnectionUtil::started");
|
||||
return true;
|
||||
}
|
||||
|
||||
void CellularConnectionUtil::stop()
|
||||
{
|
||||
log_info("CellularConnectionUtil::stop");
|
||||
_cellularDevice->close_power();
|
||||
_cellularDevice->close_network();
|
||||
if (_queue_thread) {
|
||||
_queue_thread->terminate();
|
||||
_queue_thread = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void CellularConnectionUtil::set_serial(UARTSerial *serial)
|
||||
{
|
||||
_serial = serial;
|
||||
}
|
||||
|
||||
void CellularConnectionUtil::set_callback(mbed::Callback<int(int, int)> status_callback)
|
||||
{
|
||||
_status_callback = status_callback;
|
||||
}
|
||||
|
||||
EventQueue *CellularConnectionUtil::get_queue()
|
||||
{
|
||||
return &_queue;
|
||||
}
|
||||
|
||||
CellularNetwork* CellularConnectionUtil::get_network()
|
||||
{
|
||||
if (_state != STATE_READY) {
|
||||
return NULL;
|
||||
}
|
||||
return _network;
|
||||
}
|
||||
|
||||
CellularDevice* CellularConnectionUtil::get_device()
|
||||
{
|
||||
|
||||
if (_cellularDevice) {
|
||||
return _cellularDevice;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright (c) 2017, 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 _CELLULAR_CONNECTION_UTIL_H
|
||||
#define _CELLULAR_CONNECTION_UTIL_H
|
||||
|
||||
#include <UARTSerial.h>
|
||||
#include <NetworkInterface.h>
|
||||
#include <EventQueue.h>
|
||||
|
||||
#include "CellularNetwork.h"
|
||||
#include "CellularPower.h"
|
||||
|
||||
// modem type is defined as CELLULAR_DEVICE macro
|
||||
#define _CELLULAR_STRINGIFY(a) #a
|
||||
#define CELLULAR_STRINGIFY(a) _CELLULAR_STRINGIFY(a)
|
||||
#include "CellularTargets.h"
|
||||
#include CELLULAR_STRINGIFY(CELLULAR_DEVICE.h)
|
||||
|
||||
class CellularConnectionUtil
|
||||
{
|
||||
public:
|
||||
enum CellularState {
|
||||
STATE_POWER_ON = 0,
|
||||
STATE_SELF_TEST = 1,
|
||||
STATE_START_CELLULAR = 2,
|
||||
STATE_SIM_PIN = 3,
|
||||
STATE_REGISTER_NETWORK = 4,
|
||||
STATE_REGISTERING_NETWORK = 5,
|
||||
STATE_ATTACH_NETWORK = 7,
|
||||
STATE_ATTACHING_NETWORK = 8,
|
||||
STATE_CONNECT_NETWORK = 9,
|
||||
STATE_READY = 10,
|
||||
};
|
||||
|
||||
public:
|
||||
CellularConnectionUtil();
|
||||
virtual ~CellularConnectionUtil();
|
||||
void set_serial(UARTSerial *serial);
|
||||
void set_callback(mbed::Callback<int(int, int)> status_callback);
|
||||
EventQueue* get_queue();
|
||||
bool start(bool start_dispatch = true);
|
||||
void stop();
|
||||
CellularNetwork* get_network();
|
||||
CellularDevice* get_device();
|
||||
bool continue_with_state(CellularState state);
|
||||
|
||||
protected:
|
||||
bool open_power(FileHandle *fh);
|
||||
bool open_sim();
|
||||
bool open_network();
|
||||
bool get_network_registration(CellularNetwork::RegistrationType type, CellularNetwork::RegistrationStatus &status, bool &is_registered);
|
||||
bool set_network_registration(char *plmn = 0);
|
||||
bool get_attach_network(CellularNetwork::AttachStatus &status);
|
||||
bool set_attach_network();
|
||||
|
||||
private:
|
||||
bool run_self_tests();
|
||||
void report_failure(const char* msg);
|
||||
void event();
|
||||
|
||||
UARTSerial *_serial;
|
||||
CellularState _state;
|
||||
CellularState _next_state;
|
||||
|
||||
mbed::Callback<int(int, int)> _status_callback;
|
||||
|
||||
CellularNetwork *_network;
|
||||
CellularPower *_power;
|
||||
EventQueue _queue;
|
||||
Thread *_queue_thread;
|
||||
CellularDevice *_cellularDevice;
|
||||
};
|
||||
|
||||
|
||||
#endif /* _CELLULAR_CONNECTION_UTIL_H */
|
|
@ -0,0 +1,115 @@
|
|||
/* 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.h>
|
||||
|
||||
#include "CellularConnectionUtil.h"
|
||||
#include "CellularTargets.h"
|
||||
#include "CellularUtil.h"
|
||||
#include "CellularConnectionUtil.h"
|
||||
|
||||
#include "EasyCellularConnection.h"
|
||||
|
||||
#include "CellularLog.h"
|
||||
|
||||
static CellularConnectionUtil cellularConnection;
|
||||
static rtos::Semaphore cellularSemaphore(0);
|
||||
static UARTSerial cellularSerial(MDMTXD, MDMRXD, MBED_CONF_APP_CELLULAR_SERIAL_SPEED);
|
||||
|
||||
static int cellular_status(int state, int next_state)
|
||||
{
|
||||
if (state == CellularConnectionUtil::STATE_READY) {
|
||||
MBED_ASSERT(cellularSemaphore.release() == osOK);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
EasyCellularConnection::EasyCellularConnection()
|
||||
{
|
||||
log_info("EasyCellularConnection start");
|
||||
#if defined (MDMRTS) && defined (MDMCTS)
|
||||
log_info("Serial RTS/CTS flow control in use");
|
||||
cellularSerial.set_flow_control(SerialBase::RTSCTS, MDMRTS, MDMCTS);
|
||||
#endif
|
||||
cellularConnection.set_serial(&cellularSerial);
|
||||
cellularConnection.set_callback(callback(cellular_status));
|
||||
}
|
||||
|
||||
EasyCellularConnection::~EasyCellularConnection()
|
||||
{
|
||||
cellularConnection.stop();
|
||||
}
|
||||
|
||||
void EasyCellularConnection::set_credentials(const char *apn, const char *uname, const char *pwd)
|
||||
{
|
||||
}
|
||||
|
||||
/* if (cellularConnection.start()) {
|
||||
int ret_wait = cellularSemaphore.wait(180*1000);
|
||||
if (ret_wait == 1) {
|
||||
network_interface = cellularConnection.get_network();
|
||||
if (network_interface) {
|
||||
connect_success = true;
|
||||
}
|
||||
if (log_messages) {
|
||||
printf("[EasyConnect] Cellular connection %s!\n", connect_success?"succesful":"failed");
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
void EasyCellularConnection::set_sim_pin(const char *sim_pin)
|
||||
{
|
||||
//go_to_state();
|
||||
}
|
||||
|
||||
nsapi_error_t EasyCellularConnection::connect(const char *sim_pin, const char *apn, const char *uname, const char *pwd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
nsapi_error_t EasyCellularConnection::connect()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
nsapi_error_t EasyCellularConnection::disconnect()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool EasyCellularConnection::is_connected()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *EasyCellularConnection::get_ip_address()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *EasyCellularConnection::get_netmask()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *EasyCellularConnection::get_gateway()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetworkStack *EasyCellularConnection::get_stack()
|
||||
{
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
/* 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 EASY_CELLULAR_CONNECTION_H
|
||||
#define EASY_CELLULAR_CONNECTION_H
|
||||
|
||||
#include "netsocket/CellularBase.h"
|
||||
|
||||
/** ExampleCellularBase class
|
||||
*
|
||||
* A simplified example about how to use cellular
|
||||
*/
|
||||
class EasyCellularConnection: public CellularBase {
|
||||
|
||||
public:
|
||||
EasyCellularConnection();
|
||||
virtual ~EasyCellularConnection();
|
||||
|
||||
public:
|
||||
|
||||
/** Set the Cellular network credentials
|
||||
*
|
||||
* Please check documentation of connect() for default behaviour of APN settings.
|
||||
*
|
||||
* @param apn Access point name
|
||||
* @param uname optionally, Username
|
||||
* @param pwd optionally, password
|
||||
*/
|
||||
virtual void set_credentials(const char *apn, const char *uname = 0,
|
||||
const char *pwd = 0);
|
||||
|
||||
/** Set the pin code for SIM card
|
||||
*
|
||||
* @param sim_pin PIN for the SIM card
|
||||
*/
|
||||
virtual void set_sim_pin(const char *sim_pin);
|
||||
|
||||
/** Start the interface
|
||||
*
|
||||
* Attempts to connect to a Cellular network.
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
virtual nsapi_error_t connect(const char *sim_pin, const char *apn = 0,
|
||||
const char *uname = 0,
|
||||
const char *pwd = 0);
|
||||
|
||||
/** Start the interface
|
||||
*
|
||||
* Attempts to connect to a Cellular network.
|
||||
* If the SIM requires a PIN, and it is not set/invalid, NSAPI_ERROR_AUTH_ERROR is returned.
|
||||
*
|
||||
* @return NSAPI_ERROR_OK on success, or negative error code on failure
|
||||
*/
|
||||
virtual nsapi_error_t connect();
|
||||
|
||||
/** Stop the interface
|
||||
*
|
||||
* @return 0 on success, or error code on failure
|
||||
*/
|
||||
virtual nsapi_error_t disconnect();
|
||||
|
||||
/** Check if the connection is currently established or not
|
||||
*
|
||||
* @return true/false If the cellular module have successfully acquired a carrier and is
|
||||
* connected to an external packet data network using PPP, isConnected()
|
||||
* API returns true and false otherwise.
|
||||
*/
|
||||
virtual bool is_connected();
|
||||
|
||||
/** Get the local IP address
|
||||
*
|
||||
* @return Null-terminated representation of the local IP address
|
||||
* or null if no IP address has been received
|
||||
*/
|
||||
virtual const char *get_ip_address();
|
||||
|
||||
/** Get the local network mask
|
||||
*
|
||||
* @return Null-terminated representation of the local network mask
|
||||
* or null if no network mask has been received
|
||||
*/
|
||||
virtual const char *get_netmask();
|
||||
|
||||
/** Get the local gateways
|
||||
*
|
||||
* @return Null-terminated representation of the local gateway
|
||||
* or null if no network mask has been received
|
||||
*/
|
||||
virtual const char *get_gateway();
|
||||
|
||||
protected:
|
||||
|
||||
/** Provide access to the NetworkStack object
|
||||
*
|
||||
* @return The underlying NetworkStack object
|
||||
*/
|
||||
virtual NetworkStack *get_stack();
|
||||
};
|
||||
|
||||
#endif // EASY_CELLULAR_CONNECTION_H
|
||||
|
||||
/** @}*/
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Copyright (c) 2017, 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 CELLULAR_DEVICE_H_
|
||||
#define CELLULAR_DEVICE_H_
|
||||
|
||||
#include "FileHandle.h"
|
||||
|
||||
#include "CellularSIM.h"
|
||||
#include "CellularNetwork.h"
|
||||
#include "CellularSMS.h"
|
||||
#include "CellularPower.h"
|
||||
#include "CellularMultiplexer.h"
|
||||
#include "CellularInformation.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
/**
|
||||
* Class CellularDevice
|
||||
*
|
||||
* An abstract interface that defines opening and closing of cellular interfaces.
|
||||
* Deleting/Closing of opened interfaces can be done only via this class.
|
||||
*/
|
||||
class CellularDevice
|
||||
{
|
||||
public:
|
||||
/** virtual Destructor
|
||||
*/
|
||||
virtual ~CellularDevice() {}
|
||||
|
||||
public:
|
||||
/** Create new CellularNetwork interface.
|
||||
*
|
||||
* @param fh file handle used in communication to modem. Can be for example UART handle.
|
||||
* @return New instance of interface CellularNetwork.
|
||||
*/
|
||||
virtual CellularNetwork *open_network(FileHandle *fh) = 0;
|
||||
|
||||
/** Create new CellularSMS interface.
|
||||
*
|
||||
* @param fh file handle used in communication to modem. Can be for example UART handle.
|
||||
* @return New instance of interface CellularSMS.
|
||||
*/
|
||||
virtual CellularSMS *open_sms(FileHandle *fh) = 0;
|
||||
|
||||
/** Create new CellularPower interface.
|
||||
*
|
||||
* @param fh file handle used in communication to modem. Can be for example UART handle.
|
||||
* @return New instance of interface CellularPower.
|
||||
*/
|
||||
virtual CellularPower *open_power(FileHandle *fh) = 0;
|
||||
|
||||
/** Create new CellularSIM interface.
|
||||
*
|
||||
* @param fh file handle used in communication to modem. Can be for example UART handle.
|
||||
* @return New instance of interface CellularSIM.
|
||||
*/
|
||||
virtual CellularSIM *open_sim(FileHandle *fh) = 0;
|
||||
|
||||
/** Create new CellularMultiplexer interface.
|
||||
*
|
||||
* @param fh file handle used in communication to modem. Can be for example UART handle.
|
||||
* @return New instance of interface CellularMultiplexer.
|
||||
*/
|
||||
virtual CellularMultiplexer *open_multiplexer(FileHandle *fh) = 0;
|
||||
|
||||
/** Create new CellularInformation interface.
|
||||
*
|
||||
* @param fh file handle used in communication to modem. Can be for example UART handle.
|
||||
* @return New instance of interface CellularInformation.
|
||||
*/
|
||||
virtual CellularInformation *open_information(FileHandle *fh) = 0;
|
||||
|
||||
/** Closes the opened CellularNetwork by deleting the CellularNetwork instance.
|
||||
*/
|
||||
virtual void close_network() = 0;
|
||||
|
||||
/** Closes the opened CellularNetwork by deleting the CellularSMS instance.
|
||||
*/
|
||||
virtual void close_sms() = 0;
|
||||
|
||||
/** Closes the opened CellularNetwork by deleting the CellularPower instance.
|
||||
*/
|
||||
virtual void close_power() = 0;
|
||||
|
||||
/** Closes the opened CellularNetwork by deleting the CellularSIM instance.
|
||||
*/
|
||||
virtual void close_sim() = 0;
|
||||
|
||||
/** Closes the opened CellularNetwork by deleting the CellularMultiplexer instance.
|
||||
*/
|
||||
virtual void close_multiplexer() = 0;
|
||||
|
||||
/** Closes the opened CellularNetwork by deleting the CellularInformation instance.
|
||||
*/
|
||||
virtual void close_information() = 0;
|
||||
|
||||
/** Set the default response timeout.
|
||||
*
|
||||
* @param timeout milliseconds to wait response from modem
|
||||
*/
|
||||
virtual void set_timeout(int timeout) = 0;
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
||||
#endif // CELLULAR_DEVICE_H_
|
|
@ -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 CELLULAR_INFORMATION_H_
|
||||
#define CELLULAR_INFORMATION_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include "nsapi_types.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
/**
|
||||
* Class CellularInformation
|
||||
*
|
||||
* An abstract interface that provides information about cellular device.
|
||||
*/
|
||||
class CellularInformation
|
||||
{
|
||||
protected:
|
||||
// friend of CellularDevice so that it's the only way to close/delete this class.
|
||||
friend class CellularDevice;
|
||||
|
||||
/** virtual Destructor
|
||||
*/
|
||||
virtual ~CellularInformation() {};
|
||||
|
||||
public:
|
||||
/** Request manufacturer identification of cellular device
|
||||
*
|
||||
* @param buf manufacturer identification
|
||||
* @param buf_size max length of manufacturer identification is 2048 characters
|
||||
* @return on success read character count, on failure negative error code
|
||||
*/
|
||||
virtual nsapi_size_or_error_t get_manufacturer(char *buf, size_t buf_size) = 0;
|
||||
|
||||
/** Request model identification of cellular device
|
||||
*
|
||||
* @param buf model identification
|
||||
* @param buf_size max length of model identification is 2048 characters
|
||||
* @return on success read character count, on failure negative error code
|
||||
*/
|
||||
virtual nsapi_size_or_error_t get_model(char *buf, size_t buf_size) = 0;
|
||||
|
||||
/** Request revision identification of cellular device
|
||||
*
|
||||
* @param buf revision identification
|
||||
* @param buf_size max length of revision identification is 2048 characters
|
||||
* @return on success read character count, on failure negative error code
|
||||
*/
|
||||
virtual nsapi_size_or_error_t get_revision(char *buf, size_t buf_size) = 0;
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
||||
#endif // CELLULAR_INFORMATION_H_
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 2017, 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 CELLULAR_MULTIPLEXER_H_
|
||||
#define CELLULAR_MULTIPLEXER_H_
|
||||
|
||||
#include "nsapi_types.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
/**
|
||||
* Class CellularMultiplexer
|
||||
*
|
||||
* An abstract interface that provides a way to start multiplexer mode in modem.
|
||||
*/
|
||||
class CellularMultiplexer
|
||||
{
|
||||
protected:
|
||||
// friend of CellularDevice so that it's the only way to close/delete this class.
|
||||
friend class CellularDevice;
|
||||
|
||||
/** virtual Destructor
|
||||
*/
|
||||
virtual ~CellularMultiplexer() {};
|
||||
|
||||
public:
|
||||
|
||||
/** Starts modem multiplexer mode specified by 3GPP TS 27.010.
|
||||
*
|
||||
* @return zero on success, negative error code on failure
|
||||
*/
|
||||
virtual nsapi_error_t multiplexer_mode_start() = 0;
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
||||
#endif // CELLULAR_MULTIPLEXER_H_
|
|
@ -0,0 +1,382 @@
|
|||
/*
|
||||
* Copyright (c) 2017, 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 CELLULAR_NETWORK_H_
|
||||
#define CELLULAR_NETWORK_H_
|
||||
|
||||
#include "CellularInterface.h"
|
||||
#include "NetworkInterface.h"
|
||||
#include "CellularList.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
/**
|
||||
* Class CellularNetwork
|
||||
*
|
||||
* An abstract interface for connecting to a network and getting information from it.
|
||||
*/
|
||||
class CellularNetwork : public NetworkInterface
|
||||
{
|
||||
protected:
|
||||
// friend of CellularDevice so that it's the only way to close/delete this class.
|
||||
friend class CellularDevice;
|
||||
|
||||
/**
|
||||
* virtual Destructor
|
||||
*/
|
||||
virtual ~CellularNetwork() {}
|
||||
|
||||
public:
|
||||
/* Definition for Supported CIoT EPS optimizations type. */
|
||||
enum Supported_UE_Opt {
|
||||
SUPPORTED_UE_OPT_NO_SUPPORT = 0, /* No support. */
|
||||
SUPPORTED_UE_OPT_CONTROL_PLANE, /* Support for control plane CIoT EPS optimization. */
|
||||
SUPPORTED_UE_OPT_USER_PLANE, /* Support for user plane CIoT EPS optimization. */
|
||||
SUPPORTED_UE_OPT_BOTH, /* Support for both control plane CIoT EPS optimization and user plane CIoT EPS
|
||||
optimization. */
|
||||
SUPPORTED_UE_OPT_MAX
|
||||
};
|
||||
|
||||
/* Definition for Preferred CIoT EPS optimizations type. */
|
||||
enum Preferred_UE_Opt {
|
||||
PREFERRED_UE_OPT_NO_PREFERENCE = 0, /* No preference. */
|
||||
PREFERRED_UE_OPT_CONTROL_PLANE, /* Preference for control plane CIoT EPS optimization. */
|
||||
PREFERRED_UE_OPT_USER_PLANE, /* Preference for user plane CIoT EPS optimization. */
|
||||
PREFERRED_UE_OPT_MAX
|
||||
};
|
||||
|
||||
/* Network registration status */
|
||||
enum RegistrationStatus {
|
||||
NotRegistered = 0,
|
||||
RegisteredHomeNetwork,
|
||||
SearchingNetwork,
|
||||
RegistrationDenied,
|
||||
Unknown,
|
||||
RegisteredRoaming,
|
||||
RegisteredSMSOnlyHome,
|
||||
RegisteredSMSOnlyRoaming,
|
||||
AttachedEmergencyOnly,
|
||||
RegisteredCSFBNotPreferredHome,
|
||||
RegisteredCSFBNotPreferredRoaming = 10
|
||||
};
|
||||
|
||||
/* Network registration type */
|
||||
enum RegistrationType {
|
||||
C_EREG = 0,
|
||||
C_GREG,
|
||||
C_REG,
|
||||
C_MAX
|
||||
};
|
||||
|
||||
/* device attach status to network */
|
||||
enum AttachStatus {
|
||||
Detached = 0,
|
||||
Attached,
|
||||
};
|
||||
|
||||
/* whether the additional exception reports are allowed to be sent when the maximum uplink rate is reached */
|
||||
enum RateControlExceptionReports {
|
||||
NotAllowedToBeSent = 0,
|
||||
AllowedToBeSent
|
||||
};
|
||||
|
||||
/* specifies the time unit to be used for the maximum uplink rate */
|
||||
enum RateControlUplinkTimeUnit {
|
||||
Unrestricted = 0,
|
||||
Minute,
|
||||
Hour,
|
||||
Day,
|
||||
Week
|
||||
};
|
||||
|
||||
/* authentication type when activating or modifying the pdp context */
|
||||
enum AuthenticationType {
|
||||
NOAUTH = 0,
|
||||
PAP,
|
||||
CHAP
|
||||
};
|
||||
|
||||
// 3GPP TS 27.007 - 7.3 PLMN selection +COPS
|
||||
struct operator_t {
|
||||
enum Status {
|
||||
Unknown,
|
||||
Available,
|
||||
Current,
|
||||
Forbiden
|
||||
};
|
||||
|
||||
enum RadioAccessTechnology {
|
||||
RAT_GSM,
|
||||
RAT_GSM_COMPACT,
|
||||
RAT_UTRAN,
|
||||
RAT_EGPRS,
|
||||
RAT_HSDPA,
|
||||
RAT_HSUPA,
|
||||
RAT_HSDPA_HSUPA,
|
||||
RAT_E_UTRAN,
|
||||
RAT_CATM1,
|
||||
RAT_NB1,
|
||||
RAT_UNKNOWN
|
||||
};
|
||||
|
||||
|
||||
Status op_status;
|
||||
char op_long[16+9];
|
||||
char op_short[8+4];
|
||||
char op_num[8+4];
|
||||
RadioAccessTechnology op_rat;
|
||||
operator_t *next;
|
||||
|
||||
operator_t() {
|
||||
op_status = Unknown;
|
||||
op_rat = RAT_UNKNOWN;
|
||||
next = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
typedef CellularList<operator_t> operList_t;
|
||||
|
||||
/* PDP Context information */
|
||||
struct pdpcontext_params_t {
|
||||
char apn[100+1];
|
||||
char local_addr[63+1];
|
||||
char local_subnet_mask[63+1];
|
||||
char gateway_addr[63+1];
|
||||
char dns_primary_addr[63+1];
|
||||
char dns_secondary_addr[63+1];
|
||||
char p_cscf_prim_addr[63+1];
|
||||
char p_cscf_sec_addr[63+1];
|
||||
int cid;
|
||||
int bearer_id;
|
||||
int im_signalling_flag;
|
||||
int lipa_indication;
|
||||
int ipv4_mtu;
|
||||
int wlan_offload;
|
||||
int local_addr_ind;
|
||||
int non_ip_mtu;
|
||||
int serving_plmn_rate_control_value;
|
||||
pdpcontext_params_t* next;
|
||||
|
||||
pdpcontext_params_t() {
|
||||
apn[0] = '\0';
|
||||
local_addr[0] = '\0';
|
||||
local_subnet_mask[0] = '\0';
|
||||
gateway_addr[0] = '\0';
|
||||
dns_primary_addr[0] = '\0';
|
||||
dns_secondary_addr[0] = '\0';
|
||||
p_cscf_prim_addr[0] = '\0';
|
||||
p_cscf_sec_addr[0] = '\0';
|
||||
cid = -1;
|
||||
bearer_id = -1;
|
||||
im_signalling_flag = -1;
|
||||
lipa_indication = -1;
|
||||
ipv4_mtu = -1;
|
||||
wlan_offload = -1;
|
||||
local_addr_ind = -1;
|
||||
non_ip_mtu = -1;
|
||||
serving_plmn_rate_control_value = -1;
|
||||
next = NULL;
|
||||
}
|
||||
};
|
||||
typedef CellularList<pdpcontext_params_t> pdpContextList_t;
|
||||
|
||||
/** Request registering to network.
|
||||
*
|
||||
* @param plmn format is in numeric format or 0 for automatic network registration
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t set_registration(char *plmn = 0) = 0;
|
||||
|
||||
/** Gets the network registration status.
|
||||
*
|
||||
* @param type see RegistrationType values
|
||||
* @param status see RegistrationStatus values
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t get_registration_status(RegistrationType type, RegistrationStatus &status) = 0;
|
||||
|
||||
/** Set the cellular network APN and credentials
|
||||
*
|
||||
* @param apn Optional name of the network to connect to
|
||||
* @param username Optional username for the APN
|
||||
* @param password Optional password fot the APN
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
virtual nsapi_error_t set_credentials(const char *apn,
|
||||
const char *username = 0, const char *password = 0) = 0;
|
||||
|
||||
/** Set the cellular network APN and credentials
|
||||
*
|
||||
* @param apn Name of the network to connect to
|
||||
* @param type Authentication type to use
|
||||
* @param username Optional username for the APN
|
||||
* @param password Optional password fot the APN
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
virtual nsapi_error_t set_credentials(const char *apn, AuthenticationType type,
|
||||
const char *username = 0, const char *password = 0) = 0;
|
||||
|
||||
/** Request attach to network.
|
||||
*
|
||||
* @param timeout milliseconds to wait for attach response
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t set_attach(int timeout = 10*1000) = 0;
|
||||
|
||||
/** Request attach status from network.
|
||||
*
|
||||
* @param status see AttachStatus values
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t get_attach(AttachStatus &status) = 0;
|
||||
|
||||
/** Get APN rate control.
|
||||
*
|
||||
* @remark optional params are not updated if not received from network, so use good defaults
|
||||
* @param reports Additional exception reports at maximum rate reached are allowed to be sent [optional]
|
||||
* @param time_unit Uplink time unit with values 0=unrestricted, 1=minute, 2=hour, 3=day, 4=week [optional]
|
||||
* @param uplink_rate Maximum number of messages per timeUnit [optional]
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t get_rate_control(CellularNetwork::RateControlExceptionReports &reports,
|
||||
CellularNetwork::RateControlUplinkTimeUnit &time_unit, int &uplink_rate) = 0;
|
||||
|
||||
/** Get backoff timer value
|
||||
*
|
||||
* @param backoff_time Backoff timer value associated with PDP APN in seconds
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t get_backoff_time(int &backoff_time) = 0;
|
||||
|
||||
/** Sets radio access technology.
|
||||
*
|
||||
* @param op_rat Radio access technology
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t set_access_technology(operator_t::RadioAccessTechnology op_rat) = 0;
|
||||
|
||||
/** Scans for operators module can reach.
|
||||
*
|
||||
* @param operators Container of reachable operators and their access technologies
|
||||
* @param ops_count Number of found operators
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t scan_plmn(operList_t &operators, int &ops_count) = 0;
|
||||
|
||||
/** Set CIoT optimizations.
|
||||
*
|
||||
* @param supported_opt Supported CIoT EPS optimizations.
|
||||
* @param preferred_opt Preferred CIoT EPS optimizations.
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t set_ciot_optimization_config(Supported_UE_Opt supported_opt,
|
||||
Preferred_UE_Opt preferred_opt) = 0;
|
||||
|
||||
/** Get CIoT optimizations.
|
||||
*
|
||||
* @param supported_opt Supported CIoT EPS optimizations.
|
||||
* @param preferred_opt Preferred CIoT EPS optimizations.
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t get_ciot_optimization_config(Supported_UE_Opt& supported_opt,
|
||||
Preferred_UE_Opt& preferred_opt) = 0;
|
||||
|
||||
/** Start the interface. Attempts to connect to a cellular network.
|
||||
*
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
virtual nsapi_error_t connect() = 0;
|
||||
|
||||
/** Start the interface. Attempts to connect to a cellular network.
|
||||
*
|
||||
* @param apn Optional name of the network to connect to
|
||||
* @param username Optional username for your APN
|
||||
* @param password Optional password for your APN
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
virtual nsapi_error_t connect(const char *apn,
|
||||
const char *username = 0, const char *password = 0) = 0;
|
||||
|
||||
/**
|
||||
* Set the pdn type to be used
|
||||
*
|
||||
* @param stack_type the stack type to be used.
|
||||
*
|
||||
* @return NSAPI_ERROR_OK on success
|
||||
*/
|
||||
virtual nsapi_error_t set_stack_type(nsapi_ip_stack_t stack_type) = 0;
|
||||
|
||||
/**
|
||||
* Get the pdn type in use
|
||||
*
|
||||
* @return stack type
|
||||
*/
|
||||
virtual nsapi_ip_stack_t get_stack_type() = 0;
|
||||
|
||||
/** Get the relevant information for an active non secondary PDP context.
|
||||
*
|
||||
* @remark optional params are not updated if not received from network.
|
||||
* @param params_list reference to linked list which is filled on successful call
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
virtual nsapi_error_t get_pdpcontext_params(pdpContextList_t& params_list) = 0;
|
||||
|
||||
/** Get extended signal quality parameters.
|
||||
*
|
||||
* @param rxlev signal strength level
|
||||
* @param ber bit error rate
|
||||
* @param rscp signal code power
|
||||
* @param ecno ratio of the received energy per PN chip to the total received power spectral density
|
||||
* @param rsrq signal received quality
|
||||
* @param rsrp signal received power
|
||||
* @return NSAPI_ERROR_OK on success, negative error code on failure
|
||||
*/
|
||||
virtual nsapi_error_t get_extended_signal_quality(int &rxlev, int &ber, int &rscp, int &ecno, int &rsrq, int &rsrp) = 0;
|
||||
|
||||
/** Get signal quality parameters.
|
||||
*
|
||||
* @param rssi signal strength level
|
||||
* @param ber bit error rate
|
||||
* @return NSAPI_ERROR_OK on success, negative error code on failure
|
||||
*/
|
||||
virtual nsapi_error_t get_signal_quality(int &rssi, int &ber) = 0;
|
||||
|
||||
/** Get cell id.
|
||||
*
|
||||
* @param cell_id cell id
|
||||
* @return NSAPI_ERROR_OK on success, negative error code on failure
|
||||
*/
|
||||
virtual nsapi_error_t get_cell_id(int &cell_id) = 0;
|
||||
|
||||
/** Get the last 3GPP error code
|
||||
* @return see 3GPP TS 27.007 error codes
|
||||
*/
|
||||
virtual uint8_t get_3gpp_error() = 0;
|
||||
|
||||
/** Get the operator params
|
||||
*
|
||||
* @param format format of the operator field
|
||||
* @param operator_params applicable operator param fields filled
|
||||
* @return NSAPI_ERROR_OK on success, negative error code on failure
|
||||
*/
|
||||
virtual nsapi_error_t get_operator_params(int &format, operator_t &operator_params) = 0;
|
||||
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
||||
#endif // CELLULAR_NETWORK_H_
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* Copyright (c) 2017, 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 CELLULAR_API_CELLULARPOWER_H_
|
||||
#define CELLULAR_API_CELLULARPOWER_H_
|
||||
|
||||
#include "nsapi_types.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
/**
|
||||
* Class CellularPower
|
||||
*
|
||||
* An abstract interface for connecting to a network and getting information from it.
|
||||
*/
|
||||
class CellularPower
|
||||
{
|
||||
protected:
|
||||
// friend of CellularDevice so that it's the only way to close/delete this class.
|
||||
friend class CellularDevice;
|
||||
|
||||
/**
|
||||
* virtual Destructor
|
||||
*/
|
||||
virtual ~CellularPower() {}
|
||||
|
||||
public:
|
||||
/* Access technology used in method opt_receive_period */
|
||||
enum EDRXAccessTechnology {
|
||||
EDRXGSM_EC_GSM_IoT_mode = 1,
|
||||
EDRXGSM_A_Gb_mode,
|
||||
EDRXUTRAN_Iu_mode,
|
||||
EDRXEUTRAN_WB_S1_mode,
|
||||
EDRXEUTRAN_NB_S1_mode
|
||||
};
|
||||
|
||||
/** Set cellular device power on. Default implementation is empty.
|
||||
* Device power on/off is modem/board specific behavior and must be done on inherited class if needed.
|
||||
* Power on is done by toggling power pin/button.
|
||||
*
|
||||
* @remark set_at_mode must be called to initialise modem
|
||||
*
|
||||
* @remark Should not be called if MUX is enabled and started. If called then start-up sequence must be done again.
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t on() = 0;
|
||||
|
||||
/** Set cellular device power off. Default implementation is empty.
|
||||
* Device power on/off is modem/board specific behavior and must be done on inherited class if needed.
|
||||
* Power off is done by toggling power pin/button.
|
||||
*
|
||||
* @remark Should not be called if MUX is enabled and started. If called then start-up sequence must be done again.
|
||||
*
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t off() = 0;
|
||||
|
||||
/** Set AT command mode. Blocking until success or failure.
|
||||
*
|
||||
* @remark must be called after power on to prepare correct AT mode
|
||||
*
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t set_at_mode() = 0;
|
||||
|
||||
/** Set cellular device power level by enabling/disabling functionality.
|
||||
*
|
||||
* @param func_level:
|
||||
* 0 minimum functionality
|
||||
* 1 full functionality. Enable (turn on) the transmit and receive RF circuits for all supported radio access technologies.
|
||||
* For MTs supporting +CSRA, this equals the RATs indicated by the response of +CSRA=?. Current +CSRA setting is ignored.
|
||||
* It is not required that the MT transmit and receive RF circuits are in a disabled state for this setting to have effect.
|
||||
* 2 disable (turn off) MT transmit RF circuits only
|
||||
* 3 disable (turn off) MT receive RF circuits only
|
||||
* 4 disable (turn off) both MT transmit and receive RF circuits
|
||||
*
|
||||
* @remark See 3GPP TS 27.007 CFUN for more details
|
||||
* @remark Should not be called if MUX is enabled and started. If called then start-up sequence must be done again.
|
||||
*
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t set_power_level(int func_level) = 0;
|
||||
|
||||
/** Reset and wake-up cellular device.
|
||||
*
|
||||
* @remark Should not be called if MUX is enabled and started. If called then start-up sequence must be done again.
|
||||
*
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t reset() = 0;
|
||||
|
||||
/** Opt for power save setting on cellular device. If both parameters are zero then disables PSM.
|
||||
*
|
||||
* @remark See 3GPP TS 27.007 PSM for details
|
||||
*
|
||||
* @param periodic_time Timeout in seconds IoT subsystem is not expecting messaging
|
||||
* @param active_time Timeout in seconds IoT subsystem waits for response
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t opt_power_save_mode(int periodic_time, int active_time) = 0;
|
||||
|
||||
/** Opt for discontinuous reception on cellular device.
|
||||
*
|
||||
* @remark See 3GPP TS 27.007 eDRX for details.
|
||||
*
|
||||
* @param mode disable or enable the use of eDRX
|
||||
* @param act_type type of access technology
|
||||
* @param edrx_value requested edxr value. Extended DRX parameters information element.
|
||||
*
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t opt_receive_period(int mode, EDRXAccessTechnology act_type, uint8_t edrx_value) = 0;
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
||||
#endif /* CELLULAR_API_CELLULARPOWER_H_ */
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Copyright (c) 2017, 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 CELLULAR_SIM_H_
|
||||
#define CELLULAR_SIM_H_
|
||||
|
||||
#include "nsapi_types.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
const int MAX_SIM_READY_WAITING_TIME = 30;
|
||||
|
||||
/**
|
||||
* Class CellularSIM
|
||||
*
|
||||
* An abstract interface for SIM card handling.
|
||||
*/
|
||||
class CellularSIM
|
||||
{
|
||||
protected:
|
||||
// friend of CellularDevice so that it's the only way to close/delete this class.
|
||||
friend class CellularDevice;
|
||||
|
||||
/**
|
||||
* virtual Destructor
|
||||
*/
|
||||
virtual ~CellularSIM() {};
|
||||
|
||||
public:
|
||||
/* enumeration for possible SIM states */
|
||||
enum SimState {
|
||||
SimStateReady = 0,
|
||||
SimStatePinNeeded,
|
||||
SimStatePukNeeded,
|
||||
SimStateUnknown
|
||||
};
|
||||
|
||||
/** Open the SIM card by setting the pin code for SIM.
|
||||
*
|
||||
* @param sim_pin PIN for the SIM card
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t set_pin(const char *sim_pin) = 0;
|
||||
|
||||
/**Change sim pin code.
|
||||
*
|
||||
* @param sim_pin Current PIN for sim
|
||||
* @param new_pin New PIN for sim
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t change_pin(const char *sim_pin, const char *new_pin) = 0;
|
||||
|
||||
/** Change is pin query needed after boot
|
||||
*
|
||||
* @param sim_pin Valid PIN for SIM card
|
||||
* @param query_pin False is PIN query not needed, True if PIN query needed after boot.
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t set_pin_query(const char *sim_pin, bool query_pin) = 0;
|
||||
|
||||
/** Get sim card's state
|
||||
*
|
||||
* @param state current state of SIM
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t get_sim_state(SimState &state) = 0;
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
||||
#endif // CELLULAR_SIM_H_
|
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
* Copyright (c) 2017, 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 CELLULAR_SMS_H_
|
||||
#define CELLULAR_SMS_H_
|
||||
|
||||
#include "Callback.h"
|
||||
#include "nsapi_types.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
// including trailing '\0'
|
||||
const uint16_t SMS_MAX_SIZE_WITH_CONCATENATION = 4096 + 1;
|
||||
const uint16_t SMS_MAX_PHONE_NUMBER_SIZE = 20 + 1;
|
||||
const uint16_t SMS_MAX_TIME_STAMP_SIZE = 20 + 1;
|
||||
|
||||
const uint16_t SMS_MAX_SIZE_8BIT_SINGLE_SMS_SIZE = 140;
|
||||
const uint16_t SMS_MAX_SIZE_GSM7_SINGLE_SMS_SIZE = 160;
|
||||
|
||||
const uint16_t SMS_SIM_WAIT_TIME_MILLISECONDS = 200;
|
||||
|
||||
const int SMS_ERROR_MULTIPART_ALL_PARTS_NOT_READ = -5001;
|
||||
|
||||
/**
|
||||
* Class CellularSMS
|
||||
*
|
||||
* An abstract interface for SMS sending and reading.
|
||||
*/
|
||||
class CellularSMS
|
||||
{
|
||||
protected:
|
||||
// friend of CellularDevice so that it's the only way to close/delete this class.
|
||||
friend class CellularDevice;
|
||||
|
||||
/**
|
||||
* virtual Destructor
|
||||
*/
|
||||
virtual ~CellularSMS() {};
|
||||
public:
|
||||
|
||||
/* Enumeration for possible SMS modes, PDU and Text */
|
||||
enum CellularSMSMmode {
|
||||
CellularSMSMmodePDU = 0,
|
||||
CellularSMSMmodeText
|
||||
};
|
||||
|
||||
/** Does all the necessary initializations needed for receiving and sending sms.
|
||||
*
|
||||
* @param mode enumeration for choosing the correct mode: text/pdu
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t initialize(CellularSMSMmode mode) = 0;
|
||||
|
||||
/** Send the SMS with the given parameters
|
||||
*
|
||||
* @param phone_number Phone number where to send sms
|
||||
* @param message SMS message content
|
||||
* @param msg_len Length of the message
|
||||
* @return possible error code or length of the sent sms
|
||||
*/
|
||||
virtual nsapi_size_or_error_t send_sms(const char* phone_number, const char* message, int msg_len) = 0;
|
||||
|
||||
/** Gets the oldest received sms.
|
||||
*
|
||||
* @param buf preallocated buffer for sms message content
|
||||
* @param buf_len length of allocated buf
|
||||
* @param phone_num preallocated buffer for phone number where sms was sent
|
||||
* @param phone_len length of allocated phone_num buffer
|
||||
* @param time_stamp preallocated buffer for TP-Service Centre Time Stamp (format: yy/MM/dd,hh:mm:ss-+zz). +-zz is timezone.
|
||||
* The unit of time zone is a quarter of an hour relative to GMT. For example +32 would be GMT+8.
|
||||
* @param time_len length of allocated time_stamp buffer
|
||||
* @param buf_size if method return error NSAPI_ERROR_NO_MEMORY because the given buf was not big enough this will
|
||||
* hold the size which is enough. Otherwise zero.
|
||||
* @return possible error code or size of buf. Will return SMS_ERROR_MULTIPART_ALL_PARTS_NOT_READ
|
||||
* if sms was multipart but not all parts are present/failed to read.
|
||||
*/
|
||||
virtual nsapi_size_or_error_t get_sms(char* buf, uint16_t buf_len, char* phone_num, uint16_t phone_len,
|
||||
char* time_stamp, uint16_t time_len, int *buf_size) = 0;
|
||||
|
||||
/** Callback which is called when new sms is received. SMS can be fetched via method get_sms().
|
||||
*
|
||||
* @remark In PDU mode there can be multipart sms and callback is called for every received part.
|
||||
*
|
||||
* @param func Callback function which is called when new sms is received.
|
||||
*/
|
||||
virtual void set_sms_callback(Callback<void()> func) = 0;
|
||||
|
||||
/** CPMS preferred message storage
|
||||
*
|
||||
* @param memr memory from which messages are read and deleted
|
||||
* "SM" - SIM SMS memory storage (default)
|
||||
* "ME" - NVM SMS storage
|
||||
* @param memw memory to which writing and sending operations are made
|
||||
* "SM" - SIM SMS memory storage (default)
|
||||
* "ME" - NVM SMS storage
|
||||
* @param mems memory to which received SMs are preferred to be stored
|
||||
* "SM" - SIM SMS memory storage (default)
|
||||
* "ME" - NVM SMS storage
|
||||
*
|
||||
* @return 1 for success, 0 for failure
|
||||
*/
|
||||
virtual nsapi_error_t set_cpms(const char *memr, const char *memw, const char *mems) = 0;
|
||||
|
||||
/** CSCA - set Service Center Address
|
||||
*
|
||||
* @param sca Service Center Address to be used for mobile originated SMS transmissions.
|
||||
* @param type 129 - national numbering scheme, 145 - international numbering scheme (contains the character "+")
|
||||
*
|
||||
* @return 1 for success, 0 for failure
|
||||
*/
|
||||
virtual nsapi_error_t set_csca(const char *sca, int type) = 0;
|
||||
|
||||
/** Set command sets the current character set used by the device. "GSM", "IRA",....
|
||||
*
|
||||
* @remark Current implementation support only ASCII so choose the correct character set.
|
||||
*
|
||||
* @param chr_set preferred character set list (comma separated). Modem might not support the wanted character set
|
||||
* so chr_set list is looped from start until supported set is found. Used character set index is returned.
|
||||
* See more from 3GPP TS 27.005.
|
||||
* @return Used character set index from the given list in case of success. Otherwise negative errorcode.
|
||||
*/
|
||||
virtual nsapi_size_or_error_t set_cscs(const char *chr_set) = 0;
|
||||
|
||||
/** Deletes all messages from the currently set memory/SIM
|
||||
*
|
||||
* @return possible error code
|
||||
*/
|
||||
virtual nsapi_error_t delete_all_messages() = 0;
|
||||
|
||||
/** Some modems need extra time between AT commands and responses or there will be error -314, SIM busy.
|
||||
* If SIM busy errors are an issue this time should be increased. It can also be set to zero to make
|
||||
* operations faster and more energy efficient if no errors will follow. By default wait time is zero.
|
||||
*
|
||||
* @param sim_wait_time
|
||||
*/
|
||||
virtual void set_extra_sim_wait_time(int sim_wait_time) = 0;
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
||||
#endif // CELLULAR_SMS_H_
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,471 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef AT_HANDLER_H_
|
||||
#define AT_HANDLER_H_
|
||||
|
||||
#include "platform/mbed_retarget.h"
|
||||
#include "stdio.h"
|
||||
|
||||
#include "EventQueue.h"
|
||||
#include "PlatformMutex.h"
|
||||
#include "nsapi_types.h"
|
||||
|
||||
#include "PlatformMutex.h"
|
||||
#include "Callback.h"
|
||||
#include "EventQueue.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
class FileHandle;
|
||||
|
||||
/**
|
||||
* If application calls associated FileHandle only from single thread context
|
||||
* then locking between AT command and response is not needed. However,
|
||||
* note that many cellular functions are called indirectly e.g. via socket API.
|
||||
* If you are unsure then AT_HANDLER_MUTEX must be defined.
|
||||
*/
|
||||
#define AT_HANDLER_MUTEX
|
||||
|
||||
extern const char *OK;
|
||||
extern const char *CRLF;
|
||||
|
||||
#define BUFF_SIZE 16
|
||||
|
||||
/* AT Error types enumeration */
|
||||
enum DeviceErrorType {
|
||||
DeviceErrorTypeNoError = 0,
|
||||
DeviceErrorTypeError, // AT ERROR
|
||||
DeviceErrorTypeErrorCMS, // AT ERROR CMS
|
||||
DeviceErrorTypeErrorCME // AT ERROR CME
|
||||
};
|
||||
|
||||
/* struct used when getting at response error. Defines error code and type */
|
||||
struct device_err_t {
|
||||
DeviceErrorType errType;
|
||||
int errCode;
|
||||
};
|
||||
|
||||
/** Class ATHandler
|
||||
*
|
||||
* Class for sending AT commands and parsing AT responses.
|
||||
*/
|
||||
class ATHandler
|
||||
{
|
||||
|
||||
public:
|
||||
/** Constructor
|
||||
*
|
||||
* @param fh file handle used for reading AT responses and writing AT commands
|
||||
* @param queue Event queue used to transfer sigio events to this thread
|
||||
* @param timeout Timeout when reading for AT response
|
||||
* @param output_delimiter Default delimiter used when parsing at responses
|
||||
*/
|
||||
ATHandler(FileHandle *fh, events::EventQueue &queue, int timeout, const char *output_delimiter = "\r");
|
||||
~ATHandler();
|
||||
|
||||
/** Return used file handle.
|
||||
*
|
||||
* @return used file handle
|
||||
*/
|
||||
FileHandle *get_file_handle();
|
||||
|
||||
/** Set file handle which is used for reading AT responses and writing AT commands
|
||||
*
|
||||
* @param fh file handle used for reading AT responses and writing AT commands
|
||||
*/
|
||||
void set_file_handle(FileHandle *fh);
|
||||
|
||||
/** Locks the mutex for file handle if AT_HANDLER_MUTEX is defined.
|
||||
*/
|
||||
void lock();
|
||||
|
||||
/** Unlocks the mutex for file handle if AT_HANDLER_MUTEX is defined.
|
||||
*/
|
||||
void unlock();
|
||||
|
||||
/** Locks the mutex for file handle if AT_HANDLER_MUTEX is defined and returns the last error.
|
||||
*
|
||||
* @return last error which happened when parsing AT responses
|
||||
*/
|
||||
nsapi_error_t unlock_return_error();
|
||||
|
||||
/** Set the urc callback for urc. If urc is found when parsing AT responses then call if called.
|
||||
*
|
||||
* @param prefix Register urc prefix for callback. Urc could be for example "+CMTI: "
|
||||
* @param callback Callback which is called if urc is found in AT response
|
||||
*/
|
||||
void set_urc_handler(const char *prefix, mbed::Callback<void()> callback);
|
||||
|
||||
ATHandler *_nextATHandler; // linked list
|
||||
|
||||
/** returns the last error while parsing AT responses.
|
||||
*
|
||||
* @return last error
|
||||
*/
|
||||
nsapi_error_t get_last_error() const;
|
||||
|
||||
/** returns the last device error while parsing AT responses. Actually AT error (CME/CMS).
|
||||
*
|
||||
* @return last error struct device_err_t
|
||||
*/
|
||||
device_err_t get_last_device_error() const;
|
||||
|
||||
/** Increase reference count. Used for counting references to this instance.
|
||||
*/
|
||||
void inc_ref_count();
|
||||
|
||||
/** Decrease reference count. Used for counting references to this instance.
|
||||
*/
|
||||
void dec_ref_count();
|
||||
|
||||
/** Get the current reference count. Used for counting references to this instance.
|
||||
*
|
||||
* @return current reference count
|
||||
*/
|
||||
int get_ref_count();
|
||||
|
||||
/** Set timeout in milliseconds for AT commands
|
||||
*
|
||||
* @param timeout_milliseconds Timeout in milliseconds
|
||||
* @param default_timeout Store as default timeout
|
||||
*/
|
||||
void set_at_timeout(uint32_t timeout_milliseconds, bool default_timeout = false);
|
||||
|
||||
/** Restore timeout to previous timeout. Handy if there is a need to change timeout temporarily.
|
||||
*/
|
||||
void restore_at_timeout();
|
||||
|
||||
/** Clear pending error flag. By default error is cleared only in lock().
|
||||
*/
|
||||
void clear_error();
|
||||
|
||||
/** Tries to find oob's from the AT response. Call the urc callback if one is found.
|
||||
*/
|
||||
void process_oob();
|
||||
|
||||
/** Set sigio for the current file handle. Sigio event goes through eventqueue so that it's handled in current thread.
|
||||
*/
|
||||
void set_filehandle_sigio();
|
||||
|
||||
/**
|
||||
* Flushes the underlying stream
|
||||
*/
|
||||
void flush();
|
||||
|
||||
protected:
|
||||
void event();
|
||||
#ifdef AT_HANDLER_MUTEX
|
||||
PlatformMutex _fileHandleMutex;
|
||||
#endif
|
||||
FileHandle *_fileHandle;
|
||||
private:
|
||||
|
||||
void set_error(nsapi_error_t err);
|
||||
void set_oobs_matching_param(bool);
|
||||
|
||||
events::EventQueue &_queue;
|
||||
nsapi_error_t _last_err;
|
||||
nsapi_error_t _last_3gpp_error;
|
||||
device_err_t _last_at_err;
|
||||
uint16_t _oob_string_max_length;
|
||||
char *_output_delimiter;
|
||||
uint8_t _output_delimiter_length;
|
||||
|
||||
struct oob_t {
|
||||
bool matching_to_received;
|
||||
const char *prefix;
|
||||
mbed::Callback<void()> cb;
|
||||
oob_t *next;
|
||||
};
|
||||
oob_t *_oobs;
|
||||
bool _response_terminated;
|
||||
uint32_t _at_timeout;
|
||||
uint32_t _previous_at_timeout;
|
||||
|
||||
bool _fh_sigio_set;
|
||||
|
||||
bool _processing;
|
||||
int32_t _ref_count;
|
||||
|
||||
//*************************************
|
||||
public:
|
||||
|
||||
/** Starts the command writing by clearing the last error and writing the given command.
|
||||
* In case of failure when writing the last error is set to NSAPI_ERROR_DEVICE_ERROR.
|
||||
*
|
||||
* @param cmd AT command to be written to modem
|
||||
*/
|
||||
void cmd_start(const char* cmd);
|
||||
|
||||
/** Writes integer type AT command subparameter. Starts with the delimiter if not the first param after cmd_start.
|
||||
* In case of failure when writing the last error is set to NSAPI_ERROR_DEVICE_ERROR.
|
||||
*
|
||||
* @param param int to be written to modem as AT command subparameter
|
||||
*/
|
||||
void write_int(int32_t param);
|
||||
|
||||
/** Writes string type AT command subparamater. Quotes are added to surround the given string.
|
||||
* Starts with the delimiter if not the first param after cmd_start.
|
||||
* In case of failure when writing the last error is set to NSAPI_ERROR_DEVICE_ERROR.
|
||||
*
|
||||
* @param param string to be written to modem as AT command subparameter
|
||||
* @param useQuotations flag indicating if the string should be or not included in quotation marks
|
||||
*/
|
||||
void write_string(const char* param, bool useQuotations = true);
|
||||
|
||||
/** Stops the AT command by writing command line terminator CR to mark command as finished.
|
||||
*/
|
||||
void cmd_stop();
|
||||
|
||||
/** Write bytes without any subparameter delimiters, such as comma.
|
||||
* In case of failure when writing the last error is set to NSAPI_ERROR_DEVICE_ERROR.
|
||||
*
|
||||
* @param data bytes to be written to modem
|
||||
* @param len length of data string
|
||||
*
|
||||
* @return number of characters successfully written
|
||||
*/
|
||||
size_t write_bytes(uint8_t *data, size_t len);
|
||||
|
||||
/** Sets the stop tag for the current scope(response/information response/element)
|
||||
* Parameter's reading routines will stop the reading when such tag is found and will set the found flag.
|
||||
* Consume routines will read everything until such tag is found.
|
||||
*
|
||||
* @param stop_tag_seq string to be set as stop tag
|
||||
*/
|
||||
void set_stop_tag(const char *stop_tag_seq);
|
||||
|
||||
/** Sets the delimiter between parameters or between elements of the information response.
|
||||
* Parameter's reading routines will stop when such char is read.
|
||||
*
|
||||
* @param delimiter char to be set as _delimiter
|
||||
*/
|
||||
void set_delimiter(char delimiter);
|
||||
|
||||
/** Consumes the reading buffer up to the delimiter or stop_tag
|
||||
*
|
||||
* @param count number of parameters to be skipped
|
||||
*/
|
||||
void skip_param(uint32_t count = 1);
|
||||
|
||||
/** Consumes the given length from the reading buffer
|
||||
*
|
||||
* @param len length to be consumed from reading buffer
|
||||
* @param count number of parameters to be skipped
|
||||
*/
|
||||
void skip_param(ssize_t len, uint32_t count);
|
||||
|
||||
/** Reads given number of bytes from receiving buffer without checking any subparameter delimiters, such as comma.
|
||||
*
|
||||
* @param buf output buffer for the read
|
||||
* @param len maximum number of bytes to read
|
||||
* @return number of successfully read bytes or -1 in case of error
|
||||
*/
|
||||
ssize_t read_bytes(uint8_t *buf, size_t len);
|
||||
|
||||
/** Reads chars from reading buffer. Terminates with null. Skips the quotation marks.
|
||||
* Stops on delimiter or stop tag.
|
||||
*
|
||||
* @param str output buffer for the read
|
||||
* @param size maximum number of chars to output
|
||||
* @param read_even_stop_tag if true then try to read even the stop tag was found previously
|
||||
* @return length of output string or -1 in case of read timeout before delimiter or stop tag is found
|
||||
*/
|
||||
ssize_t read_string(char *str, size_t size, bool read_even_stop_tag = false);
|
||||
|
||||
/** Reads as string and converts result to integer. Supports only positive integers.
|
||||
*
|
||||
* @return the positive integer or -1 in case of error.
|
||||
*/
|
||||
int32_t read_int();
|
||||
|
||||
/** This looks for necessary matches: prefix, OK, ERROR, URCs and sets the correct scope.
|
||||
*
|
||||
* @param prefix string to be matched from receiving buffer. If not NULL and match succeeds, then scope
|
||||
* will be set as information response(info_type)
|
||||
* @param stop flag to indicate if we go to information response scope or not.
|
||||
* (needed when nothing is expected to be received anymore after the prefix match:
|
||||
* sms case: "> ", bc95 reboot case)
|
||||
*/
|
||||
void resp_start(const char *prefix = NULL, bool stop = false);
|
||||
|
||||
/** Ends all scopes starting from current scope.
|
||||
* Consumes everything until the scope's stop tag is found, then
|
||||
* goes to next scope, until response scope is ending.
|
||||
* Possible sequence:
|
||||
* element scope -> information response scope -> response scope
|
||||
*/
|
||||
void resp_stop();
|
||||
|
||||
/** Looks for matching the prefix given to resp_start() call.
|
||||
* If needed it ends the scope of a previous information response.
|
||||
* Sets the information response scope if new prefix is found and response scope if prefix is not found.
|
||||
*
|
||||
* @return true if new information response is found, false otherwise
|
||||
*/
|
||||
bool info_resp();
|
||||
|
||||
/** Looks for matching the start tag.
|
||||
* If needed it ends the scope of a previous element.
|
||||
* Sets the element scope if start tag is found and information response scope if start tag is not found.
|
||||
*
|
||||
* @param start_tag tag to be matched to begin parsing an element of an information response
|
||||
* @return true if new element is found, false otherwise
|
||||
*/
|
||||
bool info_elem(char start_tag);
|
||||
|
||||
/** Consumes the received content until current stop tag is found.
|
||||
*
|
||||
* @return true if stop tag is found, false otherwise
|
||||
*/
|
||||
bool consume_to_stop_tag();
|
||||
|
||||
/** Sets _debug_on flag.
|
||||
*
|
||||
* @param enable value to be set for _debug_on flag
|
||||
*/
|
||||
void enable_debug(bool enable);
|
||||
|
||||
/** Return the last 3GPP error code.
|
||||
* @return last 3GPP error code
|
||||
*/
|
||||
uint8_t get_3gpp_error();
|
||||
|
||||
private:
|
||||
|
||||
// should fit any prefix and int
|
||||
char _recv_buff[BUFF_SIZE];
|
||||
// reading position
|
||||
size_t _recv_len;
|
||||
// reading length
|
||||
size_t _recv_pos;
|
||||
|
||||
// resp_type: the part of the response that doesn't include the information response(+CMD1,+CMD2..)
|
||||
// ends with OK or (CME)(CMS)ERROR
|
||||
// info_type: the information response part of the response: starts with +CMD1 and ends with CRLF
|
||||
// information response contains parameters or subsets of parameters(elements), both separated by comma
|
||||
// elem_type: subsets of parameters that are part of information response, its parameters are separated by comma
|
||||
enum ScopeType {RespType, InfoType, ElemType, NotSet};
|
||||
void set_scope(ScopeType scope_type, const char* stop_tag = NULL);
|
||||
ScopeType _current_scope;
|
||||
|
||||
struct tag_t {
|
||||
char tag[7];
|
||||
size_t len;
|
||||
bool found;
|
||||
};
|
||||
|
||||
// tag to stop response scope
|
||||
tag_t _resp_stop;
|
||||
// tag to stop information response scope
|
||||
tag_t _info_stop;
|
||||
// tag to stop element scope
|
||||
tag_t _elem_stop;
|
||||
// reference to the stop tag of current scope(resp/info/elem)
|
||||
tag_t *_stop_tag;
|
||||
|
||||
// delimiter between parameters and also used for delimiting elements of information response
|
||||
char _delimiter;
|
||||
// set true on prefix match -> indicates start of an information response or of an element
|
||||
bool _prefix_matched;
|
||||
// set true on urc match
|
||||
bool _urc_matched;
|
||||
// set true on (CME)(CMS)ERROR
|
||||
bool _error_found;
|
||||
// Max length of OK,(CME)(CMS)ERROR and URCs
|
||||
size_t _max_resp_length;
|
||||
|
||||
// prefix set during resp_start and used to try matching possible information responses
|
||||
char _info_resp_prefix[BUFF_SIZE];
|
||||
bool _debug_on;
|
||||
bool _cmd_start;
|
||||
|
||||
// Gets char from receiving buffer.
|
||||
// Resets and fills the buffer if all are already read (receiving position equals receiving length).
|
||||
int16_t get_char();
|
||||
// Sets to 0 the reading position, reading length and the whole buffer content.
|
||||
void reset_buffer();
|
||||
// Reading position set to 0 and buffer's unread content moved to beginning
|
||||
void rewind_buffer();
|
||||
// Reads from serial to receiving buffer.
|
||||
// Returns on first successful read OR on timeout.
|
||||
void fill_buffer();
|
||||
|
||||
void set_tag(tag_t* tag_dest, const char *tag_seq);
|
||||
|
||||
// Rewinds the receiving buffer and compares it against given str.
|
||||
bool match(const char* str, size_t size);
|
||||
// Iterates URCs and check if they match the receiving buffer content.
|
||||
// If URC match sets the scope to information response and after urc's cb returns
|
||||
// finishes the information response scope(consumes to CRLF).
|
||||
bool match_urc();
|
||||
// Checks if any of the error strings are matching the receiving buffer content.
|
||||
bool match_error();
|
||||
// Checks is current char in buffer matches ch and consumes it,
|
||||
// if no match lets the buffer unchanged.
|
||||
bool consume_char(char ch);
|
||||
// Consumes the received content until tag is found.
|
||||
// Consumes the tag only if consume_tag flag is true.
|
||||
bool consume_to_tag(const char *tag, bool consume_tag);
|
||||
// Checks if receiving buffer contains OK, ERROR, URC or given prefix.
|
||||
void resp(const char *prefix, bool check_urc);
|
||||
|
||||
|
||||
ScopeType get_scope();
|
||||
|
||||
// Consumes to information response stop tag which is CRLF. Sets scope to response.
|
||||
void information_response_stop();
|
||||
// Consumes to element stop tag. Sets scope to information response
|
||||
void information_response_element_stop();
|
||||
|
||||
// Reads the error code if expected and sets it as last error.
|
||||
void at_error(bool error_code, DeviceErrorType error_type);
|
||||
|
||||
/** Convert AT error code to 3GPP error codes
|
||||
* @param err AT error code read from CME/CMS ERROR responses
|
||||
* @param error_type error type (CMS/CME/ERROR)
|
||||
*/
|
||||
void set_3gpp_error(uint8_t err, DeviceErrorType error_type);
|
||||
|
||||
bool check_cmd_send();
|
||||
bool write_char(char c);
|
||||
|
||||
/** Copy content of one char buffer to another buffer and sets NULL terminator
|
||||
*
|
||||
* @param dest destination char buffer
|
||||
* @param src source char buffer
|
||||
* @param src_len number of bytes to copy
|
||||
*
|
||||
*/
|
||||
void set_string(char *dest, const char *src, size_t src_len);
|
||||
|
||||
/** Finds occurence of one char buffer inside another char buffer.
|
||||
*
|
||||
* @param dest destination char buffer
|
||||
* @param dest_len length of dest
|
||||
* @param src string to be searched for
|
||||
* @param src_len length of string to be searched for
|
||||
*
|
||||
* @return pointer to first occurrence of src in dest
|
||||
*/
|
||||
const char* mem_str(const char* dest, size_t dest_len, const char* src, size_t src_len);
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
||||
#endif //AT_HANDLER_H_
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "AT_CellularBase.h"
|
||||
|
||||
using namespace mbed;
|
||||
|
||||
AT_CellularBase::AT_CellularBase(ATHandler& at) : _at(at)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ATHandler& AT_CellularBase::get_at_handler()
|
||||
{
|
||||
return _at;
|
||||
}
|
||||
|
||||
device_err_t AT_CellularBase::get_device_error() const
|
||||
{
|
||||
return _at.get_last_device_error();
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef AT_CELLULAR_BASE_H_
|
||||
#define AT_CELLULAR_BASE_H_
|
||||
|
||||
#include "ATHandler.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
/**
|
||||
* Class AT_CellularBase
|
||||
*
|
||||
* A base class for AT-classes.
|
||||
*/
|
||||
class AT_CellularBase
|
||||
{
|
||||
public:
|
||||
AT_CellularBase(ATHandler& at);
|
||||
|
||||
/** Getter for at handler. Common method for all AT-classes.
|
||||
*
|
||||
* @return reference to ATHandler
|
||||
*/
|
||||
ATHandler& get_at_handler();
|
||||
|
||||
/** Gets the device error which happened when using AT commands/responses. This is at error
|
||||
* returned by the device. Returned CME/CMS errors can be found from 3gpp documents 27007 and 27005.
|
||||
*
|
||||
* @return at error (CME/CMS) while communication with the device
|
||||
*/
|
||||
device_err_t get_device_error() const;
|
||||
|
||||
protected:
|
||||
ATHandler& _at;
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
||||
#endif /* AT_CELLULAR_BASE_H_ */
|
|
@ -0,0 +1,248 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "AT_CellularDevice.h"
|
||||
|
||||
using namespace events;
|
||||
using namespace mbed;
|
||||
|
||||
#define DEFAULT_AT_TIMEOUT 1000 // at default timeout in milliseconds
|
||||
|
||||
AT_CellularDevice::AT_CellularDevice(EventQueue &queue) :
|
||||
_atHandlers(0), _network(0), _sms(0), _sim(0), _power(0), _multiplexer(0), _information(0), _queue(queue), _default_timeout(DEFAULT_AT_TIMEOUT)
|
||||
{
|
||||
}
|
||||
|
||||
AT_CellularDevice::~AT_CellularDevice()
|
||||
{
|
||||
close_network();
|
||||
close_sms();
|
||||
close_power();
|
||||
close_sim();
|
||||
close_multiplexer();
|
||||
close_information();
|
||||
|
||||
ATHandler *atHandler = _atHandlers;
|
||||
while (atHandler) {
|
||||
ATHandler *old = atHandler;
|
||||
atHandler = atHandler->_nextATHandler;
|
||||
delete old;
|
||||
old = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// each parser is associated with one filehandle (that is UART or a MUX channel)
|
||||
ATHandler* AT_CellularDevice::get_at_handler(FileHandle *fileHandle)
|
||||
{
|
||||
if (!fileHandle) {
|
||||
return NULL;
|
||||
}
|
||||
ATHandler *atHandler = _atHandlers;
|
||||
while (atHandler) {
|
||||
if (atHandler->get_file_handle() == fileHandle) {
|
||||
atHandler->inc_ref_count();
|
||||
return atHandler;
|
||||
}
|
||||
atHandler = atHandler->_nextATHandler;
|
||||
}
|
||||
|
||||
atHandler = new ATHandler(fileHandle, _queue, _default_timeout);
|
||||
if (atHandler) {
|
||||
atHandler->_nextATHandler = _atHandlers;
|
||||
_atHandlers = atHandler;
|
||||
}
|
||||
|
||||
return atHandler;
|
||||
}
|
||||
|
||||
void AT_CellularDevice::release_at_handler(ATHandler* at_handler)
|
||||
{
|
||||
if (!at_handler) {
|
||||
return;
|
||||
}
|
||||
at_handler->dec_ref_count();
|
||||
if (at_handler->get_ref_count() == 0) {
|
||||
// we can delete this at_handler
|
||||
ATHandler *atHandler = _atHandlers;
|
||||
ATHandler *prev = NULL;
|
||||
while (atHandler) {
|
||||
if (atHandler == at_handler) {
|
||||
if (prev == NULL) {
|
||||
_atHandlers = _atHandlers->_nextATHandler;
|
||||
}
|
||||
else {
|
||||
prev->_nextATHandler = atHandler->_nextATHandler;
|
||||
}
|
||||
delete atHandler;
|
||||
atHandler = NULL;
|
||||
break;
|
||||
} else {
|
||||
prev = atHandler;
|
||||
atHandler =atHandler->_nextATHandler;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CellularNetwork *AT_CellularDevice::open_network(FileHandle *fh)
|
||||
{
|
||||
if (!_network) {
|
||||
ATHandler *atHandler = get_at_handler(fh);
|
||||
if (atHandler) {
|
||||
_network = new AT_CellularNetwork(*atHandler);
|
||||
if (!_network) {
|
||||
release_at_handler(atHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
return _network;
|
||||
}
|
||||
|
||||
CellularSMS *AT_CellularDevice::open_sms(FileHandle *fh)
|
||||
{
|
||||
if (!_sms) {
|
||||
ATHandler *atHandler = get_at_handler(fh);
|
||||
if (atHandler) {
|
||||
_sms = new AT_CellularSMS(*atHandler);
|
||||
if (!_sms) {
|
||||
release_at_handler(atHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
return _sms;
|
||||
}
|
||||
|
||||
CellularSIM *AT_CellularDevice::open_sim(FileHandle *fh)
|
||||
{
|
||||
if (!_sim) {
|
||||
ATHandler *atHandler = get_at_handler(fh);
|
||||
if (atHandler) {
|
||||
_sim = new AT_CellularSIM(*atHandler);
|
||||
if (!_sim) {
|
||||
release_at_handler(atHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
return _sim;
|
||||
}
|
||||
|
||||
CellularPower *AT_CellularDevice::open_power(FileHandle *fh)
|
||||
{
|
||||
if (!_power) {
|
||||
ATHandler *atHandler = get_at_handler(fh);
|
||||
if (atHandler) {
|
||||
_power = new AT_CellularPower(*atHandler);
|
||||
if (!_power) {
|
||||
release_at_handler(atHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
return _power;
|
||||
}
|
||||
|
||||
CellularMultiplexer *AT_CellularDevice::open_multiplexer(FileHandle *fh)
|
||||
{
|
||||
if (!_multiplexer) {
|
||||
ATHandler *atHandler = get_at_handler(fh);
|
||||
if (atHandler) {
|
||||
_multiplexer = new AT_CellularMultiplexer(*atHandler);
|
||||
if (!_multiplexer) {
|
||||
release_at_handler(atHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _multiplexer;
|
||||
}
|
||||
|
||||
CellularInformation *AT_CellularDevice::open_information(FileHandle *fh)
|
||||
{
|
||||
if (!_information) {
|
||||
ATHandler *atHandler = get_at_handler(fh);
|
||||
if (atHandler) {
|
||||
_information = new AT_CellularInformation(*atHandler);
|
||||
if (!_information) {
|
||||
release_at_handler(atHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
return _information;
|
||||
}
|
||||
|
||||
void AT_CellularDevice::close_network()
|
||||
{
|
||||
if (_network) {
|
||||
release_at_handler(&_network->get_at_handler());
|
||||
delete _network;
|
||||
_network = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void AT_CellularDevice::close_sms()
|
||||
{
|
||||
if (_sms) {
|
||||
release_at_handler(&_sms->get_at_handler());
|
||||
delete _sms;
|
||||
_sms = NULL;
|
||||
}
|
||||
}
|
||||
void AT_CellularDevice::close_power()
|
||||
{
|
||||
if (_power) {
|
||||
release_at_handler(&_power->get_at_handler());
|
||||
delete _power;
|
||||
_power = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void AT_CellularDevice::close_sim()
|
||||
{
|
||||
if (_sim) {
|
||||
release_at_handler(&_sim->get_at_handler());
|
||||
delete _sim;
|
||||
_sim = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void AT_CellularDevice::close_multiplexer()
|
||||
{
|
||||
if (_multiplexer) {
|
||||
release_at_handler(&_multiplexer->get_at_handler());
|
||||
delete _multiplexer;
|
||||
_multiplexer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void AT_CellularDevice::close_information()
|
||||
{
|
||||
if (_information) {
|
||||
release_at_handler(&_information->get_at_handler());
|
||||
delete _information;
|
||||
_information = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void AT_CellularDevice::set_timeout(int timeout)
|
||||
{
|
||||
_default_timeout = timeout;
|
||||
|
||||
ATHandler *atHandler = _atHandlers;
|
||||
while (atHandler) {
|
||||
atHandler->set_at_timeout(_default_timeout, true); // set as default timeout
|
||||
atHandler = atHandler->_nextATHandler;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef AT_CELLULAR_DEVICE_H_
|
||||
#define AT_CELLULAR_DEVICE_H_
|
||||
|
||||
#include "CellularDevice.h"
|
||||
|
||||
#include "AT_CellularNetwork.h"
|
||||
#include "AT_CellularSIM.h"
|
||||
#include "AT_CellularSMS.h"
|
||||
#include "AT_CellularPower.h"
|
||||
#include "AT_CellularMultiplexer.h"
|
||||
#include "AT_CellularInformation.h"
|
||||
|
||||
#include "ATHandler.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
class AT_CellularDevice : public CellularDevice
|
||||
{
|
||||
public:
|
||||
AT_CellularDevice(events::EventQueue &queue);
|
||||
virtual ~AT_CellularDevice();
|
||||
|
||||
protected:
|
||||
ATHandler *_atHandlers;
|
||||
|
||||
/** Get the athandler. If the given fh is already used with existing athandler, instance to that athander is returned.
|
||||
* Otherwise new athander is created.
|
||||
*
|
||||
* @param fh FileHandle to be used with the ATHandler
|
||||
* @return pointer to ATHandler
|
||||
*/
|
||||
ATHandler *get_at_handler(FileHandle *fh);
|
||||
|
||||
/** Releases the given at_handler. If last reference to at_hander then it's deleted.
|
||||
*
|
||||
* @param at_handler
|
||||
*/
|
||||
void release_at_handler(ATHandler* at_handler);
|
||||
|
||||
public: // CellularDevice
|
||||
/** Create new CellularNetwork interface.
|
||||
*
|
||||
* @param fh filehandle used in communication to modem. Can be for example UART handle.
|
||||
* @return New instance of interface CellularNetwork.
|
||||
*/
|
||||
virtual CellularNetwork *open_network(FileHandle *fh);
|
||||
|
||||
/** Create new CellularSMS interface.
|
||||
*
|
||||
* @param fh filehandle used in communication to modem. Can be for example UART handle.
|
||||
* @return New instance of interface CellularSMS.
|
||||
*/
|
||||
virtual CellularSMS *open_sms(FileHandle *fh);
|
||||
|
||||
/** Create new CellularPower interface.
|
||||
*
|
||||
* @param fh filehandle used in communication to modem. Can be for example UART handle.
|
||||
* @return New instance of interface CellularPower.
|
||||
*/
|
||||
virtual CellularPower *open_power(FileHandle *fh);
|
||||
|
||||
/** Create new CellularSIM interface.
|
||||
*
|
||||
* @param fh filehandle used in communication to modem. Can be for example UART handle.
|
||||
* @return New instance of interface CellularSIM.
|
||||
*/
|
||||
virtual CellularSIM *open_sim(FileHandle *fh);
|
||||
|
||||
/** Create new CellularMultiplexer interface.
|
||||
*
|
||||
* @param fh filehandle used in communication to modem. Can be for example UART handle.
|
||||
* @return New instance of interface CellularMultiplexer.
|
||||
*/
|
||||
virtual CellularMultiplexer *open_multiplexer(FileHandle *fh);
|
||||
|
||||
/** Create new CellularInformation interface.
|
||||
*
|
||||
* @param fh filehandle used in communication to modem. Can be for example UART handle.
|
||||
* @return New instance of interface CellularInformation.
|
||||
*/
|
||||
virtual CellularInformation *open_information(FileHandle *fh);
|
||||
|
||||
/** Closes the opened CellularNetwork by deleting the CellularNetwork instance.
|
||||
*/
|
||||
virtual void close_network();
|
||||
|
||||
/** Closes the opened CellularNetwork by deleting the CellularSMS instance.
|
||||
*/
|
||||
virtual void close_sms();
|
||||
|
||||
/** Closes the opened CellularNetwork by deleting the CellularPower instance.
|
||||
*/
|
||||
virtual void close_power();
|
||||
|
||||
/** Closes the opened CellularNetwork by deleting the CellularSIM instance.
|
||||
*/
|
||||
virtual void close_sim();
|
||||
|
||||
/** Closes the opened CellularNetwork by deleting the CellularMultiplexer instance.
|
||||
*/
|
||||
virtual void close_multiplexer();
|
||||
|
||||
/** Closes the opened CellularNetwork by deleting the CellularInformation instance.
|
||||
*/
|
||||
virtual void close_information();
|
||||
|
||||
/** Set the default response timeout.
|
||||
*
|
||||
* @param timeout milliseconds to wait response from modem
|
||||
*/
|
||||
virtual void set_timeout(int timeout);
|
||||
|
||||
protected:
|
||||
AT_CellularNetwork *_network;
|
||||
AT_CellularSMS *_sms;
|
||||
AT_CellularSIM *_sim;
|
||||
AT_CellularPower* _power;
|
||||
AT_CellularMultiplexer* _multiplexer;
|
||||
AT_CellularInformation* _information;
|
||||
|
||||
protected:
|
||||
events::EventQueue &_queue;
|
||||
int _default_timeout;
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
#endif // AT_CELLULAR_DEVICE_H_
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "AT_CellularInformation.h"
|
||||
|
||||
using namespace mbed;
|
||||
|
||||
AT_CellularInformation::AT_CellularInformation(ATHandler &at) : AT_CellularBase(at)
|
||||
{
|
||||
}
|
||||
|
||||
AT_CellularInformation::~AT_CellularInformation()
|
||||
{
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularInformation::get_manufacturer(char *buf, size_t buf_size)
|
||||
{
|
||||
return get_info("AT+CGMI", buf, buf_size);
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularInformation::get_model(char *buf, size_t buf_size)
|
||||
{
|
||||
return get_info("AT+CGMM", buf, buf_size);
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularInformation::get_revision(char *buf, size_t buf_size)
|
||||
{
|
||||
return get_info("AT+CGMR", buf, buf_size);
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularInformation::get_info(const char *cmd, char *buf, size_t buf_size)
|
||||
{
|
||||
_at.lock();
|
||||
|
||||
_at.cmd_start(cmd);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.read_string(buf, buf_size-1); // stop tag OK\r\n
|
||||
_at.resp_stop();
|
||||
|
||||
return _at.unlock_return_error();
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef AT_CELLULAR_INFORMATION_H_
|
||||
#define AT_CELLULAR_INFORMATION_H_
|
||||
|
||||
#include "CellularInformation.h"
|
||||
#include "AT_CellularBase.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
class AT_CellularInformation : public CellularInformation, public AT_CellularBase
|
||||
{
|
||||
public:
|
||||
AT_CellularInformation(ATHandler &atHandler);
|
||||
virtual ~AT_CellularInformation();
|
||||
|
||||
public:
|
||||
/** Request manufacturer identification of cellular device
|
||||
*
|
||||
* @param buf manufacturer identification
|
||||
* @param buf_size max length of manufacturer identification is 2048 characters
|
||||
* @return on success read character count, on failure negative error code
|
||||
*/
|
||||
virtual nsapi_size_or_error_t get_manufacturer(char *buf, size_t buf_size);
|
||||
|
||||
/** Request model identification of cellular device
|
||||
*
|
||||
* @param buf model identification
|
||||
* @param buf_size max length of model identification is 2048 characters
|
||||
* @return on success read character count, on failure negative error code
|
||||
*/
|
||||
virtual nsapi_size_or_error_t get_model(char *buf, size_t buf_size);
|
||||
|
||||
/** Request revision identification of cellular device
|
||||
*
|
||||
* @param buf revision identification
|
||||
* @param buf_size max length of revision identification is 2048 characters
|
||||
* @return on success read character count, on failure negative error code
|
||||
*/
|
||||
virtual nsapi_size_or_error_t get_revision(char *buf, size_t buf_size);
|
||||
|
||||
protected:
|
||||
/** Request information text from cellular device
|
||||
*
|
||||
* @param cmd 3gpp command string
|
||||
* @param buf manufacturer identification
|
||||
* @param buf_size max length of manufacturer identification is 2048 characters
|
||||
* @return on success read character count, on failure negative error code
|
||||
*/
|
||||
nsapi_error_t get_info(const char *cmd, char *buf, size_t buf_size);
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
||||
#endif // AT_CELLULAR_INFORMATION_H_
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "AT_CellularMultiplexer.h"
|
||||
#include "CellularLog.h"
|
||||
|
||||
using namespace mbed;
|
||||
|
||||
AT_CellularMultiplexer::AT_CellularMultiplexer(ATHandler &at) : AT_CellularBase(at)
|
||||
{
|
||||
}
|
||||
|
||||
AT_CellularMultiplexer::~AT_CellularMultiplexer()
|
||||
{
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularMultiplexer::multiplexer_mode_start()
|
||||
{
|
||||
log_info("multiplexer_mode_start()");
|
||||
|
||||
_at.lock();
|
||||
|
||||
_at.cmd_start("AT+CMUX=0");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
|
||||
return _at.unlock_return_error();
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef AT_CELLULAR_MULTIPLEXER_H_
|
||||
#define AT_CELLULAR_MULTIPLEXER_H_
|
||||
|
||||
#include "CellularMultiplexer.h"
|
||||
#include "AT_CellularBase.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
class AT_CellularMultiplexer : public CellularMultiplexer, public AT_CellularBase
|
||||
{
|
||||
public:
|
||||
AT_CellularMultiplexer(ATHandler &atHandler);
|
||||
virtual ~AT_CellularMultiplexer();
|
||||
|
||||
public:
|
||||
/** Starts modem multiplexer mode specified by 3GPP TS 27.010.
|
||||
*
|
||||
* @return zero on success, negative error code on failure
|
||||
*/
|
||||
virtual nsapi_error_t multiplexer_mode_start();
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
#endif /* AT_CELLULAR_MULTIPLEXER_H_ */
|
|
@ -0,0 +1,888 @@
|
|||
/*
|
||||
* Copyright (c) 2017, 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 <stdlib.h>
|
||||
#include "AT_CellularNetwork.h"
|
||||
#include "nsapi_ppp.h"
|
||||
#include "CellularUtil.h"
|
||||
#include "CellularLog.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace mbed_cellular_util;
|
||||
using namespace mbed;
|
||||
|
||||
AT_CellularNetwork::AT_CellularNetwork(ATHandler &atHandler) : AT_CellularBase(atHandler),
|
||||
_stack(NULL), _uname(NULL), _pwd(NULL), _ip_stack_type_requested(DEFAULT_STACK), _ip_stack_type(DEFAULT_STACK), _cid(-1),
|
||||
_op_act(operator_t::RAT_UNKNOWN), _authentication_type(CHAP), _last_reg_type(C_REG)
|
||||
{
|
||||
|
||||
_at.set_urc_handler("NO CARRIER", callback(this, &AT_CellularNetwork::urc_no_carrier));
|
||||
|
||||
memset(_apn, 0, MAX_APN_LENGTH);
|
||||
|
||||
#ifdef MBED_CONF_APP_CELLULAR_APN
|
||||
strncpy(_apn, MBED_CONF_APP_CELLULAR_APN, MAX_APN_LENGTH);
|
||||
log_debug("Using APN [%s] from json", _apn);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
AT_CellularNetwork::~AT_CellularNetwork()
|
||||
{
|
||||
}
|
||||
|
||||
void AT_CellularNetwork::urc_no_carrier()
|
||||
{
|
||||
if (_connection_status_cb) {
|
||||
_connection_status_cb(NSAPI_ERROR_CONNECTION_LOST);
|
||||
}
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::set_credentials(const char *apn,
|
||||
const char *username, const char *password)
|
||||
{
|
||||
strncpy(_apn, apn, MAX_APN_LENGTH);
|
||||
_uname = username;
|
||||
_pwd = password;
|
||||
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::set_credentials(const char *apn,
|
||||
AuthenticationType type, const char *username, const char *password)
|
||||
{
|
||||
strncpy(_apn, apn, MAX_APN_LENGTH);
|
||||
_uname = username;
|
||||
_pwd = password;
|
||||
_authentication_type = type;
|
||||
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::connect(const char *apn,
|
||||
const char *username, const char *password)
|
||||
{
|
||||
strncpy(_apn, apn, MAX_APN_LENGTH);
|
||||
_uname = username;
|
||||
_pwd = password;
|
||||
|
||||
return connect();
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::connect()
|
||||
{
|
||||
_at.lock();
|
||||
|
||||
nsapi_error_t err = set_context_to_be_activated();
|
||||
if (err != NSAPI_ERROR_OK) {
|
||||
_at.unlock();
|
||||
log_error("Failed to activate network context!");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = open_data_channel();
|
||||
if (err != NSAPI_ERROR_OK) {
|
||||
_at.unlock();
|
||||
log_error("Failed to open data channel!");
|
||||
return err;
|
||||
}
|
||||
|
||||
_at.unlock();
|
||||
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::open_data_channel()
|
||||
{
|
||||
//old way: _at.send("ATD*99***%d#", _cid) && _at.recv("CONNECT");
|
||||
nsapi_error_t err = NSAPI_ERROR_NO_CONNECTION;
|
||||
#if NSAPI_PPP_AVAILABLE
|
||||
log_info("Open data channel in PPP mode");
|
||||
_at.cmd_start("AT+CGDATA=\"PPP\",");
|
||||
_at.write_int(_cid);
|
||||
_at.cmd_stop();
|
||||
|
||||
_at.resp_start("CONNECT", true);
|
||||
if (_at.get_last_error()) {
|
||||
log_warn("Failed to CONNECT");
|
||||
}
|
||||
/* Initialize PPP
|
||||
* mbed_ppp_init() is a blocking call, it will block until
|
||||
* connected, or timeout after 30 seconds*/
|
||||
err = nsapi_ppp_connect(_at.get_file_handle(), _connection_status_cb, _uname, _pwd, _ip_stack_type);
|
||||
#else
|
||||
// do check for stack to validate that we have support for stack
|
||||
_stack = get_stack();
|
||||
if (!_stack) {
|
||||
return err;
|
||||
}
|
||||
log_info("Activate PDP context");
|
||||
_at.cmd_start("AT+CGACT=1,");
|
||||
_at.write_int(_cid);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
err = (_at.get_last_error() == NSAPI_ERROR_OK) ? NSAPI_ERROR_OK : NSAPI_ERROR_NO_CONNECTION;
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* User initiated disconnect
|
||||
*
|
||||
* Disconnects from PPP connection only and brings down the underlying network
|
||||
* interface
|
||||
*/
|
||||
nsapi_error_t AT_CellularNetwork::disconnect()
|
||||
{
|
||||
#if NSAPI_PPP_AVAILABLE
|
||||
return nsapi_ppp_disconnect(_at.get_file_handle());
|
||||
#else
|
||||
return NSAPI_ERROR_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
void AT_CellularNetwork::connection_status_cb(Callback<void(nsapi_error_t)> cb)
|
||||
{
|
||||
_connection_status_cb = cb;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::set_context_to_be_activated()
|
||||
{
|
||||
// try to find or create context with suitable stack
|
||||
if (!get_context(_ip_stack_type_requested)) {
|
||||
return NSAPI_ERROR_NO_CONNECTION;
|
||||
}
|
||||
|
||||
// if user has defined user name and password we need to call CGAUTH before activating or modifying context
|
||||
if (_pwd && _uname) {
|
||||
_at.cmd_start("AT+CGAUTH=");
|
||||
_at.write_int(_cid);
|
||||
_at.write_int(_authentication_type);
|
||||
_at.write_string(_uname);
|
||||
_at.write_string(_pwd);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
if (_at.get_last_error() != NSAPI_ERROR_OK) {
|
||||
return NSAPI_ERROR_AUTH_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return _at.get_last_error();
|
||||
}
|
||||
|
||||
bool AT_CellularNetwork::set_new_context(nsapi_ip_stack_t stack, int cid)
|
||||
{
|
||||
nsapi_ip_stack_t tmp_stack = stack;
|
||||
char pdp_type[8+1] = {0};
|
||||
|
||||
switch (stack) {
|
||||
case IPV4_STACK:
|
||||
strncpy(pdp_type, "IP", sizeof(pdp_type));
|
||||
break;
|
||||
case IPV6_STACK:
|
||||
strncpy(pdp_type, "IPV6", sizeof(pdp_type));
|
||||
break;
|
||||
case IPV4V6_STACK:
|
||||
strncpy(pdp_type, "IPV4V6", sizeof(pdp_type));
|
||||
break;
|
||||
default:
|
||||
strncpy(pdp_type, "", sizeof(pdp_type));
|
||||
break;
|
||||
}
|
||||
|
||||
//apn: "If the value is null or omitted, then the subscription value will be requested."
|
||||
bool success = false;
|
||||
_at.cmd_start("AT+CGDCONT=");
|
||||
_at.write_int(cid);
|
||||
_at.write_string(pdp_type);
|
||||
_at.write_string(_apn);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
success = (_at.get_last_error() == NSAPI_ERROR_OK);
|
||||
|
||||
// Fall back to ipv4
|
||||
if (!success && tmp_stack == IPV4V6_STACK) {
|
||||
tmp_stack = IPV4_STACK;
|
||||
_at.cmd_start("AT+FCLASS=0;+CGDCONT=");
|
||||
_at.write_int(cid);
|
||||
_at.write_string("IP");
|
||||
_at.write_string(_apn);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
success = (_at.get_last_error() == NSAPI_ERROR_OK);
|
||||
}
|
||||
|
||||
if (success) {
|
||||
_ip_stack_type = tmp_stack;
|
||||
_cid = cid;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool AT_CellularNetwork::get_context(nsapi_ip_stack_t requested_stack)
|
||||
{
|
||||
_at.cmd_start("AT+CGDCONT?");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start("+CGDCONT:");
|
||||
_cid = -1;
|
||||
int cid_max = 0; // needed when creating new context
|
||||
char apn[MAX_APN_LENGTH] = {0};
|
||||
int apn_len = 0;
|
||||
|
||||
while (_at.info_resp()) {
|
||||
int cid = _at.read_int();
|
||||
if (cid > cid_max) {
|
||||
cid_max = cid;
|
||||
}
|
||||
char pdp_type_from_context[10];
|
||||
int pdp_type_len = _at.read_string(pdp_type_from_context, sizeof(pdp_type_from_context) - 1);
|
||||
if (pdp_type_len > 0) {
|
||||
apn_len = _at.read_string(apn, sizeof(apn) - 1);
|
||||
if (apn_len >= 0) {
|
||||
if (strlen(_apn) && strcmp(apn, _apn) != 0 ) {
|
||||
continue;
|
||||
}
|
||||
nsapi_ip_stack_t pdp_stack = string_to_stack_type(pdp_type_from_context);
|
||||
if (pdp_stack != DEFAULT_STACK) {
|
||||
if (get_modem_stack_type(pdp_stack)) {
|
||||
if (requested_stack == IPV4_STACK) {
|
||||
if (pdp_stack == IPV4_STACK || pdp_stack == IPV4V6_STACK) {
|
||||
_ip_stack_type = pdp_stack;
|
||||
_cid = cid;
|
||||
break;
|
||||
}
|
||||
} else if (requested_stack == IPV6_STACK) {
|
||||
if (pdp_stack == IPV6_STACK || pdp_stack == IPV4V6_STACK) {
|
||||
_ip_stack_type = pdp_stack;
|
||||
_cid = cid;
|
||||
break;
|
||||
}
|
||||
} else { // accept any but prefer to IPv6
|
||||
if (pdp_stack == IPV6_STACK || pdp_stack == IPV4V6_STACK) {
|
||||
_ip_stack_type = pdp_stack;
|
||||
_cid = cid;
|
||||
break;
|
||||
}
|
||||
if (_ip_stack_type == DEFAULT_STACK) {
|
||||
_ip_stack_type = pdp_stack;
|
||||
_cid = cid;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_at.resp_stop();
|
||||
if (_cid == -1) { // no suitable context was found so create a new one
|
||||
if (!set_new_context(_ip_stack_type, cid_max+1)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// save the apn
|
||||
if (apn_len > 0 && !strlen(_apn)) {
|
||||
strncpy(_apn, apn, MAX_APN_LENGTH);
|
||||
}
|
||||
|
||||
log_debug("Context id %d", _cid);
|
||||
return true;
|
||||
}
|
||||
|
||||
nsapi_ip_stack_t AT_CellularNetwork::string_to_stack_type(const char* pdp_type)
|
||||
{
|
||||
nsapi_ip_stack_t stack = DEFAULT_STACK;
|
||||
int len = strlen(pdp_type);
|
||||
|
||||
if (len == 6 && memcmp(pdp_type, "IPV4V6", len) == 0) {
|
||||
stack = IPV4V6_STACK;
|
||||
} else if (len == 4 && memcmp(pdp_type, "IPV6", len) == 0) {
|
||||
stack = IPV6_STACK;
|
||||
} else if (len == 2 && memcmp(pdp_type, "IP", len) == 0) {
|
||||
stack = IPV4_STACK;
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::set_registration_urc(bool urc_on)
|
||||
{
|
||||
RegistrationType reg_types[] = {C_EREG, C_GREG, C_REG};
|
||||
const char *cmd_on[] = {"AT+CEREG=2", "AT+CGREG=2", "AT+CREG=2"};
|
||||
const char *cmd_off[] = {"AT+CEREG=0", "AT+CGREG=0", "AT+CREG=0"};
|
||||
for (uint8_t i=0; i<sizeof(reg_types)/sizeof(reg_types[0]); i++) {
|
||||
if (has_registration(reg_types[i])) {
|
||||
_last_reg_type = reg_types[i];
|
||||
if (urc_on) {
|
||||
_at.cmd_start(cmd_on[i]);
|
||||
_at.cmd_stop();
|
||||
} else {
|
||||
_at.cmd_start(cmd_off[i]);
|
||||
_at.cmd_stop();
|
||||
}
|
||||
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
}
|
||||
}
|
||||
return _at.get_last_error();
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::set_registration(char *plmn)
|
||||
{
|
||||
_at.lock();
|
||||
|
||||
nsapi_error_t ret = set_registration_urc(false);
|
||||
if (ret) {
|
||||
log_error("Setting registration URC failed!");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!plmn) {
|
||||
log_debug("Automatic network registration");
|
||||
_at.cmd_start("AT+COPS=0");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
} else {
|
||||
log_debug("Manual network registration to %s", plmn);
|
||||
_at.cmd_start("AT+COPS=4,2,");
|
||||
_at.write_string(plmn);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
}
|
||||
|
||||
return _at.unlock_return_error();
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::get_registration_status(RegistrationType type, RegistrationStatus &status)
|
||||
{
|
||||
int i = (int)type;
|
||||
MBED_ASSERT(i >= 0 && i < C_MAX);
|
||||
|
||||
RegistrationType reg_types[] = { C_EREG, C_GREG, C_REG};
|
||||
const char *cmd[] = { "AT+CEREG", "AT+CGREG", "AT+CREG"};
|
||||
const char *rsp[] = { "+CEREG: ", "+CGREG: ", "+CREG: "};
|
||||
|
||||
const int LAC_LENGTH = 5, CELL_ID_LENGTH = 9;
|
||||
char lac_string[LAC_LENGTH] = {0}, cell_id_string[CELL_ID_LENGTH] = {0};
|
||||
bool lac_read = false, cell_id_read = false;
|
||||
|
||||
_cell_id = -1;
|
||||
_lac = -1;
|
||||
|
||||
_at.lock();
|
||||
|
||||
if (!has_registration(reg_types[i])) {
|
||||
_at.unlock();
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
_at.cmd_start(cmd[i]);
|
||||
_at.write_string("=2", false);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
|
||||
_at.cmd_start(cmd[i]);
|
||||
_at.write_string("?", false);
|
||||
|
||||
_at.cmd_stop();
|
||||
_at.resp_start(rsp[i]);
|
||||
_at.read_int(); // ignore urc mode subparam
|
||||
status = (RegistrationStatus)_at.read_int();
|
||||
|
||||
int len = _at.read_string(lac_string, LAC_LENGTH);
|
||||
if (memcmp(lac_string, "ffff", LAC_LENGTH-1) && len >= 0) {
|
||||
lac_read = true;
|
||||
}
|
||||
|
||||
len = _at.read_string(cell_id_string, CELL_ID_LENGTH);
|
||||
if (memcmp(cell_id_string, "ffffffff", CELL_ID_LENGTH-1) && len >= 0) {
|
||||
cell_id_read = true;
|
||||
}
|
||||
|
||||
_AcT = (operator_t::RadioAccessTechnology)_at.read_int();
|
||||
|
||||
_at.resp_stop();
|
||||
|
||||
_at.cmd_start(cmd[i]);
|
||||
_at.write_string("=0", false);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
nsapi_error_t ret = _at.get_last_error();
|
||||
_at.unlock();
|
||||
|
||||
if (lac_read) {
|
||||
_lac = hex_str_to_int(lac_string, LAC_LENGTH);
|
||||
log_debug("lac %s %d", lac_string, _lac );
|
||||
}
|
||||
|
||||
if (cell_id_read) {
|
||||
_cell_id = hex_str_to_int(cell_id_string, CELL_ID_LENGTH);
|
||||
log_debug("cell_id %s %d", cell_id_string, _cell_id );
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::get_cell_id(int &cell_id)
|
||||
{
|
||||
RegistrationStatus tmp;
|
||||
|
||||
nsapi_error_t error = get_registration_status(_last_reg_type, tmp);
|
||||
|
||||
cell_id = _cell_id;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
bool AT_CellularNetwork::has_registration(RegistrationType reg_type)
|
||||
{
|
||||
(void)reg_type;
|
||||
return true;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::set_attach(int timeout)
|
||||
{
|
||||
_at.lock();
|
||||
|
||||
_at.cmd_start("AT+CGATT?");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start("+CGATT:");
|
||||
int attached_state = _at.read_int();
|
||||
_at.resp_stop();
|
||||
if (attached_state != 1) {
|
||||
log_debug("Network attach");
|
||||
_at.cmd_start("AT+CGATT=1");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
}
|
||||
|
||||
return _at.unlock_return_error();
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::get_attach(AttachStatus &status)
|
||||
{
|
||||
_at.lock();
|
||||
|
||||
_at.cmd_start("AT+CGATT?");
|
||||
_at.cmd_stop();
|
||||
|
||||
_at.resp_start("+CGATT:");
|
||||
if (_at.info_resp()) {
|
||||
int attach_status = _at.read_int();
|
||||
status = (attach_status == 1) ? Attached : Detached;
|
||||
}
|
||||
_at.resp_stop();
|
||||
|
||||
return _at.unlock_return_error();
|
||||
}
|
||||
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::get_backoff_time(int &backoffTime)
|
||||
{
|
||||
_at.lock();
|
||||
|
||||
// If apn is set
|
||||
if (strlen(_apn)) {
|
||||
_at.cmd_start("AT+CABTRDP=");
|
||||
_at.write_string(_apn);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start("+CABTRDP:");
|
||||
if (_at.info_resp()) {
|
||||
_at.skip_param();
|
||||
backoffTime = _at.read_int();
|
||||
}
|
||||
_at.resp_stop();
|
||||
}
|
||||
|
||||
return _at.unlock_return_error();
|
||||
}
|
||||
|
||||
NetworkStack *AT_CellularNetwork::get_stack()
|
||||
{
|
||||
// use lwIP/PPP if modem does not have IP stack
|
||||
#if NSAPI_PPP_AVAILABLE
|
||||
_stack = nsapi_ppp_get_stack();
|
||||
#else
|
||||
_stack = NULL;
|
||||
#endif
|
||||
return _stack;
|
||||
}
|
||||
|
||||
const char *AT_CellularNetwork::get_ip_address()
|
||||
{
|
||||
#if NSAPI_PPP_AVAILABLE
|
||||
return nsapi_ppp_get_ip_addr(_at.get_file_handle());
|
||||
#else
|
||||
if (!_stack) {
|
||||
_stack = get_stack();
|
||||
}
|
||||
if (_stack) {
|
||||
return _stack->get_ip_address();
|
||||
}
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::set_stack_type(nsapi_ip_stack_t stack_type)
|
||||
{
|
||||
|
||||
if (get_modem_stack_type(stack_type)) {
|
||||
_ip_stack_type_requested = stack_type;
|
||||
return NSAPI_ERROR_OK;
|
||||
} else {
|
||||
return NSAPI_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
nsapi_ip_stack_t AT_CellularNetwork::get_stack_type()
|
||||
{
|
||||
return _ip_stack_type;
|
||||
}
|
||||
|
||||
bool AT_CellularNetwork::get_modem_stack_type(nsapi_ip_stack_t requested_stack)
|
||||
{
|
||||
if (requested_stack == _ip_stack_type) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::set_access_technology_impl(operator_t::RadioAccessTechnology opsAct)
|
||||
{
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::set_access_technology(operator_t::RadioAccessTechnology opAct)
|
||||
{
|
||||
if (opAct == operator_t::RAT_UNKNOWN) {
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
_op_act = opAct;
|
||||
|
||||
return set_access_technology_impl(opAct);
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::scan_plmn(operList_t &operators, int &opsCount)
|
||||
{
|
||||
int idx = 0;
|
||||
|
||||
_at.lock();
|
||||
|
||||
_at.cmd_start("AT+COPS=?");
|
||||
_at.cmd_stop();
|
||||
|
||||
_at.resp_start("+COPS:");
|
||||
|
||||
int ret, error_code = -1;
|
||||
operator_t *op = NULL;
|
||||
|
||||
while (_at.info_elem('(')) {
|
||||
|
||||
op = operators.add_new();
|
||||
|
||||
op->op_status = (operator_t::Status)_at.read_int();
|
||||
_at.read_string(op->op_long, sizeof(op->op_long));
|
||||
_at.read_string(op->op_short, sizeof(op->op_short));
|
||||
_at.read_string(op->op_num, sizeof(op->op_num));
|
||||
|
||||
// Optional - try read an int
|
||||
ret = _at.read_int();
|
||||
op->op_rat = (ret == error_code) ? operator_t::RAT_UNKNOWN:(operator_t::RadioAccessTechnology)ret;
|
||||
|
||||
if ((_op_act == operator_t::RAT_UNKNOWN) ||
|
||||
((op->op_rat != operator_t::RAT_UNKNOWN) && (op->op_rat == _op_act))) {
|
||||
idx++;
|
||||
} else {
|
||||
operators.delete_last();
|
||||
}
|
||||
}
|
||||
|
||||
_at.resp_stop();
|
||||
|
||||
opsCount = idx;
|
||||
|
||||
return _at.unlock_return_error();
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::set_ciot_optimization_config(Supported_UE_Opt supported_opt,
|
||||
Preferred_UE_Opt preferred_opt)
|
||||
{
|
||||
_at.lock();
|
||||
|
||||
_at.cmd_start("AT+CCIOTOPT=");
|
||||
_at.write_int(_cid);
|
||||
_at.write_int(supported_opt);
|
||||
_at.write_int(preferred_opt);
|
||||
_at.cmd_stop();
|
||||
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
|
||||
return _at.unlock_return_error();
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::get_ciot_optimization_config(Supported_UE_Opt& supported_opt,
|
||||
Preferred_UE_Opt& preferred_opt)
|
||||
{
|
||||
_at.lock();
|
||||
|
||||
_at.cmd_start("AT+CCIOTOPT?");
|
||||
_at.cmd_stop();
|
||||
|
||||
_at.resp_start("+CCIOTOPT:");
|
||||
_at.read_int();
|
||||
if (_at.get_last_error() == NSAPI_ERROR_OK) {
|
||||
supported_opt = (Supported_UE_Opt)_at.read_int();
|
||||
preferred_opt = (Preferred_UE_Opt)_at.read_int();
|
||||
}
|
||||
|
||||
_at.resp_stop();
|
||||
|
||||
return _at.unlock_return_error();
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::get_rate_control(
|
||||
CellularNetwork::RateControlExceptionReports &reports,
|
||||
CellularNetwork::RateControlUplinkTimeUnit &timeUnit, int &uplinkRate)
|
||||
{
|
||||
|
||||
_at.lock();
|
||||
|
||||
_at.cmd_start("AT+CGAPNRC=");
|
||||
_at.write_int(_cid);
|
||||
_at.cmd_stop();
|
||||
|
||||
_at.resp_start("+CGAPNRC:");
|
||||
_at.read_int();
|
||||
if (_at.get_last_error() == NSAPI_ERROR_OK) {
|
||||
bool comma_found = true;
|
||||
int next_element = _at.read_int();
|
||||
if (next_element >= 0) {
|
||||
reports = (RateControlExceptionReports)next_element;
|
||||
log_debug("reports %d",reports);
|
||||
next_element = _at.read_int();
|
||||
} else {
|
||||
comma_found = false;
|
||||
}
|
||||
|
||||
if (comma_found && next_element >= 0) {
|
||||
timeUnit = (RateControlUplinkTimeUnit)next_element;
|
||||
log_debug("time %d",timeUnit);
|
||||
next_element = _at.read_int();
|
||||
} else {
|
||||
comma_found = false;
|
||||
}
|
||||
|
||||
if (comma_found && next_element >= 0) {
|
||||
uplinkRate = next_element;
|
||||
log_debug("rate %d",uplinkRate);
|
||||
}
|
||||
}
|
||||
_at.resp_stop();
|
||||
nsapi_error_t ret = _at.get_last_error();
|
||||
_at.unlock();
|
||||
|
||||
return (ret == NSAPI_ERROR_OK) ? NSAPI_ERROR_OK : NSAPI_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::get_pdpcontext_params(pdpContextList_t& params_list)
|
||||
{
|
||||
const int ipv6_subnet_size = 128;
|
||||
const int max_ipv6_size = 64;
|
||||
char* ipv6_and_subnetmask = (char*)malloc(ipv6_subnet_size);
|
||||
if (!ipv6_and_subnetmask) {
|
||||
return NSAPI_ERROR_NO_MEMORY;
|
||||
}
|
||||
|
||||
char* temp = (char*)malloc(max_ipv6_size);
|
||||
if (!temp) {
|
||||
free(ipv6_and_subnetmask);
|
||||
return NSAPI_ERROR_NO_MEMORY;
|
||||
}
|
||||
|
||||
_at.lock();
|
||||
|
||||
_at.cmd_start("AT+CGCONTRDP=");
|
||||
_at.write_int(_cid);
|
||||
_at.cmd_stop();
|
||||
|
||||
_at.resp_start("+CGCONTRDP:");
|
||||
pdpcontext_params_t *params = NULL;
|
||||
while (_at.info_resp()) { // response can be zero or many +CGDCONT lines
|
||||
params = params_list.add_new();
|
||||
if (!params) {
|
||||
log_warn("Could not allocate new pdpcontext_params_t");
|
||||
params_list.delete_all();
|
||||
_at.resp_stop();
|
||||
free(temp);
|
||||
free(ipv6_and_subnetmask);
|
||||
return NSAPI_ERROR_NO_MEMORY;
|
||||
}
|
||||
|
||||
params->cid = _at.read_int();
|
||||
params->bearer_id = _at.read_int();
|
||||
_at.read_string(params->apn, sizeof(params->apn));
|
||||
|
||||
// rest are optional params
|
||||
ipv6_and_subnetmask[0] = '\0';
|
||||
temp[0] = '\0';
|
||||
_at.read_string(ipv6_and_subnetmask, ipv6_subnet_size);
|
||||
separate_ip_addresses(ipv6_and_subnetmask, params->local_addr, sizeof(params->local_addr), params->local_subnet_mask, sizeof(params->local_subnet_mask));
|
||||
ipv6_and_subnetmask[0] = '\0';
|
||||
|
||||
_at.read_string(ipv6_and_subnetmask, ipv6_subnet_size);
|
||||
separate_ip_addresses(ipv6_and_subnetmask, params->gateway_addr, sizeof(params->gateway_addr), temp, max_ipv6_size);
|
||||
prefer_ipv6(params->gateway_addr, sizeof(params->gateway_addr), temp, max_ipv6_size);
|
||||
ipv6_and_subnetmask[0] = '\0';
|
||||
temp[0] = '\0';
|
||||
|
||||
_at.read_string(ipv6_and_subnetmask, ipv6_subnet_size);
|
||||
separate_ip_addresses(ipv6_and_subnetmask, params->dns_primary_addr, sizeof(params->dns_primary_addr), temp, max_ipv6_size);
|
||||
prefer_ipv6(params->dns_primary_addr, sizeof(params->dns_primary_addr), temp, max_ipv6_size);
|
||||
ipv6_and_subnetmask[0] = '\0';
|
||||
temp[0] = '\0';
|
||||
|
||||
_at.read_string(ipv6_and_subnetmask, ipv6_subnet_size);
|
||||
separate_ip_addresses(ipv6_and_subnetmask, params->dns_secondary_addr, sizeof(params->dns_secondary_addr), temp, max_ipv6_size);
|
||||
prefer_ipv6(params->dns_secondary_addr, sizeof(params->dns_secondary_addr), temp, max_ipv6_size);
|
||||
ipv6_and_subnetmask[0] = '\0';
|
||||
temp[0] = '\0';
|
||||
|
||||
_at.read_string(ipv6_and_subnetmask, ipv6_subnet_size);
|
||||
separate_ip_addresses(ipv6_and_subnetmask, params->p_cscf_prim_addr, sizeof(params->p_cscf_prim_addr), temp, max_ipv6_size);
|
||||
prefer_ipv6(params->p_cscf_prim_addr, sizeof(params->p_cscf_prim_addr), temp, max_ipv6_size);
|
||||
ipv6_and_subnetmask[0] = '\0';
|
||||
temp[0] = '\0';
|
||||
|
||||
_at.read_string(ipv6_and_subnetmask, ipv6_subnet_size);
|
||||
separate_ip_addresses(ipv6_and_subnetmask, params->p_cscf_sec_addr, sizeof(params->p_cscf_sec_addr), temp, max_ipv6_size);
|
||||
prefer_ipv6(params->p_cscf_sec_addr, sizeof(params->p_cscf_sec_addr), temp, max_ipv6_size);
|
||||
|
||||
params->im_signalling_flag = _at.read_int();
|
||||
params->lipa_indication = _at.read_int();
|
||||
params->ipv4_mtu = _at.read_int();
|
||||
params->wlan_offload = _at.read_int();
|
||||
params->local_addr_ind = _at.read_int();
|
||||
params->non_ip_mtu = _at.read_int();
|
||||
params->serving_plmn_rate_control_value = _at.read_int();
|
||||
}
|
||||
_at.resp_stop();
|
||||
|
||||
free(temp);
|
||||
free(ipv6_and_subnetmask);
|
||||
|
||||
return _at.unlock_return_error();
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::get_extended_signal_quality(int &rxlev, int &ber, int &rscp, int &ecno, int &rsrq, int &rsrp)
|
||||
{
|
||||
_at.lock();
|
||||
|
||||
_at.cmd_start("AT+CESQ");
|
||||
_at.cmd_stop();
|
||||
|
||||
_at.resp_start("+CESQ:");
|
||||
rxlev = _at.read_int();
|
||||
ber = _at.read_int();
|
||||
rscp = _at.read_int();
|
||||
ecno = _at.read_int();
|
||||
rsrq = _at.read_int();
|
||||
rsrp = _at.read_int();
|
||||
_at.resp_stop();
|
||||
if (rxlev < 0 || ber < 0 || rscp < 0 || ecno < 0 || rsrq < 0 || rsrp < 0) {
|
||||
_at.unlock();
|
||||
return NSAPI_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
return _at.unlock_return_error();
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::get_signal_quality(int &rssi, int &ber)
|
||||
{
|
||||
_at.lock();
|
||||
|
||||
_at.cmd_start("AT+CSQ");
|
||||
_at.cmd_stop();
|
||||
|
||||
_at.resp_start("+CSQ:");
|
||||
rssi = _at.read_int();
|
||||
ber = _at.read_int();
|
||||
_at.resp_stop();
|
||||
if (rssi < 0 || ber < 0) {
|
||||
_at.unlock();
|
||||
return NSAPI_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
return _at.unlock_return_error();
|
||||
}
|
||||
|
||||
/** Get the last 3GPP error code
|
||||
* @return see 3GPP TS 27.007 error codes
|
||||
*/
|
||||
uint8_t AT_CellularNetwork::get_3gpp_error()
|
||||
{
|
||||
return _at.get_3gpp_error();
|
||||
}
|
||||
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::get_operator_params(int &format, operator_t &operator_params)
|
||||
{
|
||||
_at.lock();
|
||||
|
||||
_at.cmd_start("AT+COPS?");
|
||||
_at.cmd_stop();
|
||||
|
||||
_at.resp_start("+COPS: ");
|
||||
_at.read_int(); //ignore mode
|
||||
format = _at.read_int();
|
||||
|
||||
if (_at.get_last_error() == NSAPI_ERROR_OK) {
|
||||
|
||||
switch (format) {
|
||||
case 0:
|
||||
_at.read_string(operator_params.op_long, 16+9);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
_at.read_string(operator_params.op_short, 8+4);
|
||||
break;
|
||||
|
||||
default:
|
||||
_at.read_string(operator_params.op_num, 8+4);
|
||||
break;
|
||||
}
|
||||
|
||||
operator_params.op_rat = (operator_t::RadioAccessTechnology)_at.read_int();
|
||||
}
|
||||
|
||||
_at.resp_stop();
|
||||
|
||||
return _at.unlock_return_error();
|
||||
}
|
|
@ -0,0 +1,300 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef AT_CELLULAR_NETWORK_H_
|
||||
#define AT_CELLULAR_NETWORK_H_
|
||||
|
||||
#include "CellularNetwork.h"
|
||||
#include "AT_CellularBase.h"
|
||||
#include "NetworkStack.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
#define AT_NETWORK_TRIALS 5
|
||||
#define MAX_APN_LENGTH 63
|
||||
|
||||
class AT_CellularNetwork : public CellularNetwork, public AT_CellularBase
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
AT_CellularNetwork(ATHandler &atHandler);
|
||||
virtual ~AT_CellularNetwork();
|
||||
|
||||
public: // NetworkInterface
|
||||
|
||||
/** Set the cellular network APN and credentials
|
||||
*
|
||||
* @param apn Optional name of the network to connect to
|
||||
* @param username Optional username for the APN
|
||||
* @param password Optional password fot the APN
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
virtual nsapi_error_t set_credentials(const char *apn,
|
||||
const char *username = 0, const char *password = 0);
|
||||
|
||||
/** Set the cellular network APN and credentials
|
||||
*
|
||||
* @param apn Name of the network to connect to
|
||||
* @param type Authentication type to use
|
||||
* @param username Optional username for the APN
|
||||
* @param password Optional password fot the APN
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
virtual nsapi_error_t set_credentials(const char *apn, AuthenticationType type,
|
||||
const char *username = 0, const char *password = 0);
|
||||
|
||||
/** Start the interface. Attempts to connect to a cellular network.
|
||||
*
|
||||
* @param apn Optional name of the network to connect to
|
||||
* @param username Optional username for your APN
|
||||
* @param password Optional password for your APN
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
virtual nsapi_error_t connect(const char *apn,
|
||||
const char *username = 0, const char *password = 0);
|
||||
|
||||
/** Start the interface. Attempts to connect to a cellular network.
|
||||
*
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
virtual nsapi_error_t connect();
|
||||
|
||||
/** Stop the interface
|
||||
*
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
virtual nsapi_error_t disconnect();
|
||||
|
||||
/** Provide access to the NetworkStack object
|
||||
*
|
||||
* @return The underlying NetworkStack object
|
||||
*/
|
||||
virtual NetworkStack *get_stack();
|
||||
|
||||
public: // CellularNetwork
|
||||
/** Request registering to network.
|
||||
*
|
||||
* @param plmn format is in numeric format or 0 for automatic network registration
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t set_registration(char *plmn = 0);
|
||||
|
||||
/**
|
||||
* Gets the network registration status.
|
||||
* @param type see RegistrationType values
|
||||
* @param status see RegistrationStatus values
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t get_registration_status(RegistrationType type, RegistrationStatus &status);
|
||||
|
||||
/** Request attach to network.
|
||||
*
|
||||
* @param timeout milliseconds to wait for attach response
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t set_attach(int timeout = 10*1000);
|
||||
|
||||
/** Request attach status from network.
|
||||
*
|
||||
* @param status see AttachStatus values
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t get_attach(AttachStatus &status);
|
||||
|
||||
/** Get APN rate control.
|
||||
*
|
||||
* @remark optional params are not updated if not received from network, so use good defaults
|
||||
*
|
||||
* @param reports Additional exception reports at maximum rate reached are allowed to be sent [optional]
|
||||
* @param time_unit Uplink time unit with values 0=unrestricted, 1=minute, 2=hour, 3=day, 4=week [optional]
|
||||
* @param uplink_rate Maximum number of messages per timeUnit [optional]
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t get_rate_control(CellularNetwork::RateControlExceptionReports &reports,
|
||||
CellularNetwork::RateControlUplinkTimeUnit &time_unit, int &uplink_rate);
|
||||
|
||||
/** Get backoff timer value
|
||||
*
|
||||
* @param backoff_time Backoff timer value associated with PDP APN in seconds
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t get_backoff_time(int &backoff_time);
|
||||
|
||||
/** Get notified if the connection gets lost
|
||||
*
|
||||
* @param cb user defined callback
|
||||
*/
|
||||
void connection_status_cb(Callback<void(nsapi_error_t)> cb);
|
||||
|
||||
/** Get the local IP address
|
||||
*
|
||||
* @return Null-terminated representation of the local IP address
|
||||
* or null if no IP address has been received
|
||||
*/
|
||||
virtual const char *get_ip_address();
|
||||
|
||||
/** Sets radio access technology.
|
||||
*
|
||||
* @param op_rat Radio access technology
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t set_access_technology(operator_t::RadioAccessTechnology op_rat);
|
||||
|
||||
/** Scans for operators module can reach.
|
||||
*
|
||||
* @param operators Container of reachable operators and their access technologies
|
||||
* @param ops_count Number of found operators
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t scan_plmn(operList_t &operators, int &ops_count);
|
||||
|
||||
/** Set CIoT optimizations.
|
||||
*
|
||||
* @param supported_opt Supported CIoT EPS optimizations.
|
||||
* @param preferred_opt Preferred CIoT EPS optimizations.
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t set_ciot_optimization_config(Supported_UE_Opt supported_opt,
|
||||
Preferred_UE_Opt preferred_opt);
|
||||
|
||||
/** Get CIoT optimizations.
|
||||
*
|
||||
* @param supported_opt Supported CIoT EPS optimizations.
|
||||
* @param preferred_opt Preferred CIoT EPS optimizations.
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t get_ciot_optimization_config(Supported_UE_Opt& supported_opt,
|
||||
Preferred_UE_Opt& preferred_opt);
|
||||
|
||||
|
||||
/** Set the pdn type to be used
|
||||
*
|
||||
* @param stack_type the stack type to be used.
|
||||
* @return NSAPI_ERROR_OK on success
|
||||
*/
|
||||
virtual nsapi_error_t set_stack_type(nsapi_ip_stack_t stack_type);
|
||||
|
||||
/** Get the pdn type in use
|
||||
*
|
||||
* @return stack type
|
||||
*/
|
||||
virtual nsapi_ip_stack_t get_stack_type();
|
||||
|
||||
/** Get the relevant information for an active non secondary PDP context.
|
||||
*
|
||||
* @remark optional params are not updated if not received from network.
|
||||
*
|
||||
* @param params_list reference to linked list which is filled on successful call
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
virtual nsapi_error_t get_pdpcontext_params(pdpContextList_t& params_list);
|
||||
|
||||
/** Get extended signal quality parameters.
|
||||
*
|
||||
* @param rxlev signal strength level
|
||||
* @param ber bit error rate
|
||||
* @param rscp signal code power
|
||||
* @param ecno ratio of the received energy per PN chip to the total received power spectral density
|
||||
* @param rsrq signal received quality
|
||||
* @param rsrp signal received power
|
||||
* @return NSAPI_ERROR_OK on success, negative error code on failure
|
||||
*/
|
||||
virtual nsapi_error_t get_extended_signal_quality(int &rxlev, int &ber, int &rscp, int &ecno, int &rsrq, int &rsrp);
|
||||
|
||||
/** Get signal quality parameters.
|
||||
*
|
||||
* @param rssi signal strength level
|
||||
* @param ber bit error rate
|
||||
* @return NSAPI_ERROR_OK on success, negative error code on failure
|
||||
*/
|
||||
virtual nsapi_error_t get_signal_quality(int &rssi, int &ber);
|
||||
|
||||
/** Get cell id.
|
||||
*
|
||||
* @param cell_id cell id
|
||||
* @return NSAPI_ERROR_OK on success, negative error code on failure
|
||||
*/
|
||||
virtual nsapi_error_t get_cell_id(int &cell_id);
|
||||
|
||||
/** Get the last 3GPP error code
|
||||
* @return see 3GPP TS 27.007 error codes
|
||||
*/
|
||||
virtual uint8_t get_3gpp_error();
|
||||
|
||||
/** Get the operator params
|
||||
*
|
||||
* @param format format of the operator field
|
||||
* @param operator_params applicable operator param fields filled
|
||||
* @return NSAPI_ERROR_OK on success, negative error code on failure
|
||||
*/
|
||||
virtual nsapi_error_t get_operator_params(int &format, operator_t &operator_params);
|
||||
|
||||
protected:
|
||||
|
||||
/** Check if modem supports the given stack type.
|
||||
*
|
||||
* @return true if supported
|
||||
*/
|
||||
virtual bool get_modem_stack_type(nsapi_ip_stack_t requested_stack);
|
||||
|
||||
/** Check if modem supports given registration type.
|
||||
*
|
||||
* @param reg_type enum RegistrationType
|
||||
* @return true if given registration type is supported by modem
|
||||
*/
|
||||
virtual bool has_registration(RegistrationType reg_type);
|
||||
|
||||
/** Sets access technology to be scanned.
|
||||
*
|
||||
* @param op_rat Access technology
|
||||
*
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t set_access_technology_impl(operator_t::RadioAccessTechnology op_rat);
|
||||
|
||||
private:
|
||||
// "NO CARRIER" urc
|
||||
void urc_no_carrier();
|
||||
nsapi_error_t set_context_to_be_activated();
|
||||
nsapi_ip_stack_t string_to_stack_type(const char* pdp_type);
|
||||
|
||||
nsapi_error_t open_data_channel();
|
||||
bool get_context(nsapi_ip_stack_t supported_stack);
|
||||
bool set_new_context(nsapi_ip_stack_t stack, int cid);
|
||||
nsapi_error_t set_registration_urc(bool on);
|
||||
|
||||
protected:
|
||||
NetworkStack *_stack;
|
||||
char _apn[MAX_APN_LENGTH];
|
||||
const char *_uname;
|
||||
const char *_pwd;
|
||||
nsapi_ip_stack_t _ip_stack_type_requested;
|
||||
nsapi_ip_stack_t _ip_stack_type;
|
||||
int _cid;
|
||||
Callback<void(nsapi_error_t)> _connection_status_cb;
|
||||
operator_t::RadioAccessTechnology _op_act;
|
||||
AuthenticationType _authentication_type;
|
||||
int _lac;
|
||||
int _cell_id;
|
||||
operator_t::RadioAccessTechnology _AcT;
|
||||
RegistrationType _last_reg_type;
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
||||
#endif // AT_CELLULAR_NETWORK_H_
|
|
@ -0,0 +1,232 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "AT_CellularPower.h"
|
||||
#include "CellularUtil.h"
|
||||
#include "CellularLog.h"
|
||||
|
||||
static const int PSMTimerBits = 5;
|
||||
|
||||
using namespace mbed_cellular_util;
|
||||
using namespace mbed;
|
||||
|
||||
AT_CellularPower::AT_CellularPower(ATHandler &at) : AT_CellularBase(at)
|
||||
{
|
||||
}
|
||||
|
||||
AT_CellularPower::~AT_CellularPower()
|
||||
{
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularPower::on()
|
||||
{
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularPower::off()
|
||||
{
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularPower::set_at_mode()
|
||||
{
|
||||
_at.lock();
|
||||
_at.flush();
|
||||
_at.cmd_start("ATE0"); // echo off
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
|
||||
_at.cmd_start("AT+CMEE=1"); // verbose responses
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
return _at.unlock_return_error();
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularPower::set_power_level(int func_level)
|
||||
{
|
||||
_at.lock();
|
||||
_at.cmd_start("AT+CFUN=");
|
||||
_at.write_int(func_level);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
return _at.unlock_return_error();
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularPower::reset()
|
||||
{
|
||||
_at.lock();
|
||||
_at.cmd_start("AT+CFUN=");// reset to full power levels
|
||||
_at.write_int(1);
|
||||
_at.write_int(1);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
return _at.unlock_return_error();
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularPower::opt_power_save_mode(int periodic_time, int active_time)
|
||||
{
|
||||
_at.lock();
|
||||
|
||||
if (periodic_time == 0 && active_time == 0) {
|
||||
// disable PSM
|
||||
_at.cmd_start("AT+CPSMS=");
|
||||
_at.write_int(0);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
} else {
|
||||
/**
|
||||
Table 10.5.163a/3GPP TS 24.008: GPRS Timer 3 information element
|
||||
|
||||
Bits 5 to 1 represent the binary coded timer value.
|
||||
|
||||
Bits 6 to 8 defines the timer value unit for the GPRS timer as follows:
|
||||
8 7 6
|
||||
0 0 0 value is incremented in multiples of 10 minutes
|
||||
0 0 1 value is incremented in multiples of 1 hour
|
||||
0 1 0 value is incremented in multiples of 10 hours
|
||||
0 1 1 value is incremented in multiples of 2 seconds
|
||||
1 0 0 value is incremented in multiples of 30 seconds
|
||||
1 0 1 value is incremented in multiples of 1 minute
|
||||
1 1 0 value is incremented in multiples of 320 hours (NOTE 1)
|
||||
1 1 1 value indicates that the timer is deactivated (NOTE 2).
|
||||
*/
|
||||
char pt[8+1];// timer value encoded as 3GPP IE
|
||||
const int ie_value_max = 0x1f;
|
||||
uint32_t periodic_timer = 0;
|
||||
if (periodic_time <= 2*ie_value_max) { // multiples of 2 seconds
|
||||
periodic_timer = periodic_time/2;
|
||||
strcpy(pt, "01100000");
|
||||
} else {
|
||||
if (periodic_time <= 30*ie_value_max) { // multiples of 30 seconds
|
||||
periodic_timer = periodic_time/30;
|
||||
strcpy(pt, "10000000");
|
||||
} else {
|
||||
if (periodic_time <= 60*ie_value_max) { // multiples of 1 minute
|
||||
periodic_timer = periodic_time/60;
|
||||
strcpy(pt, "10100000");
|
||||
} else {
|
||||
if (periodic_time <= 10*60*ie_value_max) { // multiples of 10 minutes
|
||||
periodic_timer = periodic_time/(10*60);
|
||||
strcpy(pt, "00000000");
|
||||
} else {
|
||||
if (periodic_time <= 60*60*ie_value_max) { // multiples of 1 hour
|
||||
periodic_timer = periodic_time/(60*60);
|
||||
strcpy(pt, "00100000");
|
||||
} else {
|
||||
if (periodic_time <= 10*60*60*ie_value_max) { // multiples of 10 hours
|
||||
periodic_timer = periodic_time/(10*60*60);
|
||||
strcpy(pt, "01000000");
|
||||
} else { // multiples of 320 hours
|
||||
int t = periodic_time / (320*60*60);
|
||||
if (t > ie_value_max) {
|
||||
t = ie_value_max;
|
||||
}
|
||||
periodic_timer = t;
|
||||
strcpy(pt, "11000000");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint_to_binary_str(periodic_timer, &pt[3], sizeof(pt)-3, PSMTimerBits);
|
||||
pt[8] = '\0';
|
||||
|
||||
/**
|
||||
Table 10.5.172/3GPP TS 24.008: GPRS Timer information element
|
||||
|
||||
Bits 5 to 1 represent the binary coded timer value.
|
||||
|
||||
Bits 6 to 8 defines the timer value unit for the GPRS timer as follows:
|
||||
|
||||
8 7 6
|
||||
0 0 0 value is incremented in multiples of 2 seconds
|
||||
0 0 1 value is incremented in multiples of 1 minute
|
||||
0 1 0 value is incremented in multiples of decihours
|
||||
1 1 1 value indicates that the timer is deactivated.
|
||||
|
||||
Other values shall be interpreted as multiples of 1 minute in this version of the protocol.
|
||||
*/
|
||||
char at[8+1];
|
||||
uint32_t active_timer; // timer value encoded as 3GPP IE
|
||||
if (active_time <= 2*ie_value_max) { // multiples of 2 seconds
|
||||
active_timer = active_time/2;
|
||||
strcpy(at, "00000000");
|
||||
} else {
|
||||
if (active_time <= 60*ie_value_max) { // multiples of 1 minute
|
||||
active_timer = (1<<5) | (active_time/60);
|
||||
strcpy(at, "00100000");
|
||||
} else { // multiples of decihours
|
||||
int t = active_time / (6*60);
|
||||
if (t > ie_value_max) {
|
||||
t = ie_value_max;
|
||||
}
|
||||
active_timer = t;
|
||||
strcpy(at, "01000000");
|
||||
}
|
||||
}
|
||||
|
||||
uint_to_binary_str(active_timer, &at[3], sizeof(at)-3, PSMTimerBits);
|
||||
pt[8] = '\0';
|
||||
|
||||
// request for both GPRS and LTE
|
||||
_at.cmd_start("AT+CPSMS=");
|
||||
_at.write_int(1);
|
||||
_at.write_string(pt);
|
||||
_at.write_string(at);
|
||||
_at.write_string(pt);
|
||||
_at.write_string(at);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
|
||||
|
||||
if (_at.get_last_error() != NSAPI_ERROR_OK) {
|
||||
log_warn("Power save mode not enabled!");
|
||||
} else {
|
||||
// network may not agree with power save options but
|
||||
// that should be fine as timeout is not longer than requested
|
||||
}
|
||||
}
|
||||
|
||||
return _at.unlock_return_error();
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularPower::opt_receive_period(int mode, EDRXAccessTechnology act_type, uint8_t edrx_value)
|
||||
{
|
||||
char edrx[5];
|
||||
uint_to_binary_str(edrx_value, edrx, 5, 4);
|
||||
edrx[4] = '\0';
|
||||
|
||||
_at.lock();
|
||||
|
||||
_at.cmd_start("AT+CEDRXS=");
|
||||
_at.write_int(mode);
|
||||
_at.write_int(act_type);
|
||||
_at.write_string(edrx);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
|
||||
return _at.unlock_return_error();
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef AT_CELLULAR_POWER_H_
|
||||
#define AT_CELLULAR_POWER_H_
|
||||
|
||||
#include "CellularPower.h"
|
||||
#include "AT_CellularBase.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
class AT_CellularPower : public CellularPower, public AT_CellularBase
|
||||
{
|
||||
public:
|
||||
AT_CellularPower(ATHandler &atHandler);
|
||||
virtual ~AT_CellularPower();
|
||||
|
||||
public:
|
||||
/** Set cellular device power on. Default implementation is empty.
|
||||
* Device power on/off is modem/board specific behavior and must be done on inherited class if needed.
|
||||
* Power on is done by toggling power pin/button.
|
||||
*
|
||||
* @remark set_at_mode must be called to initialise modem
|
||||
* @remark Should not be called if MUX is enabled and started. If called then start-up sequence must be done again.
|
||||
*
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t on();
|
||||
|
||||
/** Set cellular device power off. Default implementation is empty.
|
||||
* Device power on/off is modem/board specific behavior and must be done on inherited class if needed.
|
||||
* Power off is done by toggling power pin/button.
|
||||
*
|
||||
* @remark Should not be called if MUX is enabled and started. If called then start-up sequence must be done again.
|
||||
*
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t off();
|
||||
|
||||
/** Set AT command mode. Blocking until success or failure.
|
||||
*
|
||||
* @remark must be called after power on to prepare correct AT mode
|
||||
*
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t set_at_mode();
|
||||
|
||||
/** Set cellular device power level by enabling/disabling functionality.
|
||||
*
|
||||
* @param func_level:
|
||||
* 0 minimum functionality
|
||||
* 1 full functionality. Enable (turn on) the transmit and receive RF circuits for all supported radio access technologies.
|
||||
* For MTs supporting +CSRA, this equals the RATs indicated by the response of +CSRA=?. Current +CSRA setting is ignored.
|
||||
* It is not required that the MT transmit and receive RF circuits are in a disabled state for this setting to have effect.
|
||||
* 2 disable (turn off) MT transmit RF circuits only
|
||||
* 3 disable (turn off) MT receive RF circuits only
|
||||
* 4 disable (turn off) both MT transmit and receive RF circuits
|
||||
*
|
||||
* @remark See 3GPP TS 27.007 CFUN for more details
|
||||
* @remark Should not be called if MUX is enabled and started. If called then start-up sequence must be done again.
|
||||
*
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t set_power_level(int func_level);
|
||||
|
||||
/** Reset and wake-up cellular device.
|
||||
*
|
||||
* @remark Should not be called if MUX is enabled and started. If called then start-up sequence must be done again.
|
||||
*
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t reset();
|
||||
|
||||
/** Opt for power save setting on cellular device. If both parameters are zero then disables PSM.
|
||||
*
|
||||
* @remark See 3GPP TS 27.007 PSM for details
|
||||
*
|
||||
* @param periodic_time Timeout in seconds IoT subsystem is not expecting messaging
|
||||
* @param active_time Timeout in seconds IoT subsystem waits for response
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t opt_power_save_mode(int periodic_time, int active_time);
|
||||
|
||||
/** Opt for discontinuous reception on cellular device.
|
||||
*
|
||||
* @remark See 3GPP TS 27.007 eDRX for details.
|
||||
*
|
||||
* @param mode disable or enable the use of eDRX
|
||||
* @param act_type type of access technology
|
||||
* @param edrx_value requested edxr value. Extended DRX parameters information element.
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t opt_receive_period(int mode, EDRXAccessTechnology act_type, uint8_t edrx_value);
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
||||
#endif /* AT_CELLULAR_POWER_H_ */
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "AT_CellularSIM.h"
|
||||
#include "CellularLog.h"
|
||||
|
||||
using namespace mbed;
|
||||
|
||||
AT_CellularSIM::AT_CellularSIM(ATHandler &at) : AT_CellularBase(at)
|
||||
{
|
||||
}
|
||||
|
||||
AT_CellularSIM::~AT_CellularSIM()
|
||||
{
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularSIM::get_sim_state(SimState &state)
|
||||
{
|
||||
char simstr[16];
|
||||
_at.lock();
|
||||
_at.flush();
|
||||
_at.cmd_start("AT+CPIN?");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start("+CPIN:");
|
||||
ssize_t len = _at.read_string(simstr, sizeof (simstr));
|
||||
if (len != -1) {
|
||||
if (len >= 5 && memcmp(simstr, "READY", 5) == 0) {
|
||||
state = SimStateReady;
|
||||
} else if (len >= 6 && memcmp(simstr, "SIM PIN", 6) == 0) {
|
||||
state = SimStatePinNeeded;
|
||||
} else if (len >= 6 && memcmp(simstr, "SIM PUK", 6) == 0) {
|
||||
state = SimStatePukNeeded;
|
||||
} else {
|
||||
simstr[len] = '\0';
|
||||
log_error("Unknown SIM state %s", simstr);
|
||||
state = SimStateUnknown;
|
||||
}
|
||||
} else {
|
||||
log_warn("SIM not readable.");
|
||||
state = SimStateUnknown; // SIM may not be ready yet or +CPIN may be unsupported command
|
||||
}
|
||||
_at.resp_stop();
|
||||
return _at.unlock_return_error();
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularSIM::set_pin(const char *sim_pin)
|
||||
{
|
||||
// if SIM is already in ready state then settings the PIN
|
||||
// will return error so let's check the state before settings the pin.
|
||||
SimState state;
|
||||
if (get_sim_state(state) == NSAPI_ERROR_OK && state == SimStateReady) {
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
_at.lock();
|
||||
_at.cmd_start("AT+CPIN=");
|
||||
_at.write_string(sim_pin);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
return _at.unlock_return_error();
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularSIM::change_pin(const char *sim_pin, const char *new_pin)
|
||||
{
|
||||
_at.lock();
|
||||
_at.cmd_start("AT+CPWD=");
|
||||
_at.write_string("SC");
|
||||
_at.write_string(sim_pin);
|
||||
_at.write_string(new_pin);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
return _at.unlock_return_error();
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularSIM::set_pin_query(const char *sim_pin, bool query_pin)
|
||||
{
|
||||
_at.lock();
|
||||
if (query_pin) {
|
||||
/* use the SIM locked */
|
||||
_at.cmd_start("AT+CLCK=");
|
||||
_at.write_string("SC");
|
||||
_at.write_int(1);
|
||||
_at.write_string(sim_pin);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
} else {
|
||||
/* use the SIM unlocked */
|
||||
_at.cmd_start("AT+CLCK=");
|
||||
_at.write_string("SC");
|
||||
_at.write_int(0);
|
||||
_at.write_string(sim_pin);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
}
|
||||
return _at.unlock_return_error();
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef AT_CELLULAR_SIM_H_
|
||||
#define AT_CELLULAR_SIM_H_
|
||||
|
||||
#include "CellularSIM.h"
|
||||
#include "AT_CellularBase.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
class AT_CellularSIM : public CellularSIM, public AT_CellularBase
|
||||
{
|
||||
|
||||
public:
|
||||
AT_CellularSIM(ATHandler &atHandler);
|
||||
virtual ~AT_CellularSIM();
|
||||
|
||||
public:
|
||||
/** Open the SIM card by setting the pin code for SIM.
|
||||
*
|
||||
* @param sim_pin PIN for the SIM card
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t set_pin(const char *sim_pin);
|
||||
|
||||
/**Change sim pin code.
|
||||
*
|
||||
* @param sim_pin Current PIN for sim
|
||||
* @param new_pin New PIN for sim
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t change_pin(const char *sim_pin, const char *new_pin);
|
||||
|
||||
/** Change is pin query needed after boot
|
||||
*
|
||||
* @param sim_pin Valid PIN for SIM card
|
||||
* @param query_pin False is PIN query not needed, True if PIN query needed after boot.
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t set_pin_query(const char *sim_pin, bool query_pin);
|
||||
|
||||
/** Get sim card's state
|
||||
*
|
||||
* @param state current state of SIM
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t get_sim_state(SimState &state);
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
||||
#endif // AT_CELLULAR_SIM_H_
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,245 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef AT_CELLULAR_SMS_H_
|
||||
#define AT_CELLULAR_SMS_H_
|
||||
|
||||
#include "CellularSMS.h"
|
||||
#include "AT_CellularBase.h"
|
||||
#include <Callback.h>
|
||||
#include <time.h>
|
||||
|
||||
namespace mbed {
|
||||
|
||||
class AT_CellularSMS: public CellularSMS, public AT_CellularBase
|
||||
{
|
||||
|
||||
public:
|
||||
AT_CellularSMS(ATHandler &atHandler);
|
||||
virtual ~AT_CellularSMS();
|
||||
|
||||
public:
|
||||
// from CellularSMS
|
||||
|
||||
/** Does all the necessary initializations needed for receiving and sending sms.
|
||||
*
|
||||
* @param mode enumeration for choosing the correct mode: text/pdu
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t initialize(CellularSMSMmode mode);
|
||||
|
||||
/** Send the SMS with the given parameters
|
||||
*
|
||||
* @param phone_number Phone number where to send sms
|
||||
* @param message SMS message content
|
||||
* @param msg_len Length of the message
|
||||
* @return possible error code or length of the sent sms
|
||||
*/
|
||||
virtual nsapi_size_or_error_t send_sms(const char* phone_number, const char* message, int msg_len);
|
||||
|
||||
/** Gets the oldest received sms.
|
||||
*
|
||||
* @param buf preallocated buffer for sms message content
|
||||
* @param buf_len length of allocated buf
|
||||
* @param phone_num preallocated buffer for phone number where sms was sent
|
||||
* @param phone_len length of allocated phone_num buffer
|
||||
* @param time_stamp preallocated buffer for TP-Service Centre Time Stamp (format: yy/MM/dd,hh:mm:ss-+zz). +-zz is timezone.
|
||||
* The unit of time zone is a quarter of an hour relative to GMT. For example +32 would be GMT+8.
|
||||
* @param time_len length of allocated time_stamp buffer
|
||||
* @param buf_size if method return error NSAPI_ERROR_NO_MEMORY because the given buf was not big enough this will
|
||||
* hold the size which is enough. Otherwise zero.
|
||||
* @return possible error code or size of buf. Will return SMS_ERROR_MULTIPART_ALL_PARTS_NOT_READ
|
||||
* if sms was multipart but not all parts are present/failed to read.
|
||||
*/
|
||||
virtual nsapi_size_or_error_t get_sms(char* buf, uint16_t buf_len, char* phone_num, uint16_t phone_len,
|
||||
char* time_stamp, uint16_t time_len, int *buf_size);
|
||||
|
||||
/** Callback which is called when new sms is received. SMS can be fetched via method get_sms().
|
||||
*
|
||||
* @remark In PDU mode there can be multipart sms and callback is called for every received part.
|
||||
*
|
||||
* @param func Callback function which is called when new sms is received.
|
||||
*/
|
||||
virtual void set_sms_callback(Callback<void()> func);
|
||||
|
||||
/** CPMS preferred message storage
|
||||
*
|
||||
* @param memr memory from which messages are read and deleted
|
||||
* "SM" - SIM SMS memory storage (default)
|
||||
* "ME" - NVM SMS storage
|
||||
* @param memw memory to which writing and sending operations are made
|
||||
* "SM" - SIM SMS memory storage (default)
|
||||
* "ME" - NVM SMS storage
|
||||
* @param mems memory to which received SMs are preferred to be stored
|
||||
* "SM" - SIM SMS memory storage (default)
|
||||
* "ME" - NVM SMS storage
|
||||
*
|
||||
* @return zero for success
|
||||
*/
|
||||
virtual nsapi_error_t set_cpms(const char *memr, const char *memw, const char *mems);
|
||||
|
||||
/** CSCA - set Service Center Address
|
||||
*
|
||||
* @param sca Service Center Address to be used for mobile originated SMS transmissions.
|
||||
* @param type 129 - national numbering scheme, 145 - international numbering scheme (contains the character "+")
|
||||
*
|
||||
* @return zero for success
|
||||
*/
|
||||
virtual nsapi_error_t set_csca(const char *sca, int type);
|
||||
|
||||
/** Set command sets the current character set used by the device. "GSM", "IRA",....
|
||||
*
|
||||
* @remark Current implementation support only ASCII so choose the correct character set.
|
||||
*
|
||||
* @param chr_set preferred character set list (comma separated). Modem might not support the wanted character set
|
||||
* so chr_set list is looped from start until supported set is found. Used character set index is returned.
|
||||
* See more from 3GPP TS 27.005.
|
||||
* @return Used character set index from the given list in case of success. Otherwise negative errorcode.
|
||||
*/
|
||||
virtual nsapi_size_or_error_t set_cscs(const char *chr_set);
|
||||
|
||||
/** Deletes all messages from the currently set memory/SIM
|
||||
*
|
||||
* @return zero for success
|
||||
*/
|
||||
virtual nsapi_error_t delete_all_messages();
|
||||
|
||||
/** Some modems need extra time between AT commands and responses or there will be error -314, SIM busy.
|
||||
* If SIM busy errors are an issue this time should be increased. It can also be set to zero to make
|
||||
* operations faster and more energy efficient if no errors will follow. By default wait time is zero.
|
||||
*
|
||||
* @param sim_wait_time
|
||||
*/
|
||||
virtual void set_extra_sim_wait_time(int sim_wait_time);
|
||||
|
||||
private:
|
||||
|
||||
struct sms_info_t {
|
||||
char date[SMS_MAX_TIME_STAMP_SIZE];
|
||||
uint16_t msg_index[50]; // can hold up to 50 concatenated msg parts, indexes are in correct order. So max sms size is 50*140 = 7kb
|
||||
uint16_t msg_size;
|
||||
uint8_t parts;
|
||||
uint8_t parts_added;
|
||||
uint16_t msg_ref_number;
|
||||
struct sms_info_t *next_info;
|
||||
sms_info_t() : msg_size(0), parts(1), parts_added(1), msg_ref_number(0), next_info(0){};
|
||||
};
|
||||
|
||||
// application callback function for received sms
|
||||
Callback<void()> _cb;
|
||||
CellularSMSMmode _mode;
|
||||
bool _use_8bit_encoding;
|
||||
uint32_t _sim_wait_time;
|
||||
uint16_t _sms_message_ref_number;
|
||||
sms_info_t *_sms_info;
|
||||
|
||||
// SMS urc's
|
||||
void cmt_urc();
|
||||
void cmti_urc();
|
||||
|
||||
/** Set command selects the format of messages used with send, list, read and write commands.
|
||||
*
|
||||
* @param msg_format 0 PDU mode, 1 text mode
|
||||
* @return zero for success
|
||||
*/
|
||||
nsapi_error_t set_cmgf(int msg_format);
|
||||
|
||||
/** Select message service (AT+CSMS select message service)
|
||||
*
|
||||
* @param msg_service 0 or 1. See more from 3GPP TS 27.005
|
||||
*
|
||||
* @return zero for success
|
||||
*/
|
||||
nsapi_error_t set_csms(int msg_service);
|
||||
|
||||
/* Set how receiving of new messages from the network is indicated to the TE.
|
||||
*
|
||||
* @return zero for success
|
||||
*/
|
||||
nsapi_error_t set_cnmi();
|
||||
|
||||
/** Set Text Mode Parameters
|
||||
*
|
||||
* @param fo See more from 3GPP TS 27.005 for all params.
|
||||
* @param vp
|
||||
* @param pid
|
||||
* @param dcs
|
||||
* @return zero for success
|
||||
*/
|
||||
nsapi_error_t set_csmp(int fo, int vp, int pid, int dcs);
|
||||
|
||||
/** CSDH - Set command controls whether detailed header information is shown in text mode (AT+CMGF=1) result codes.
|
||||
*
|
||||
* @param show_header 1 to show detailed header in text mode, 0 for not showing.
|
||||
* @return zero for success
|
||||
*/
|
||||
nsapi_error_t set_csdh(int show_header);
|
||||
|
||||
/** Delete SMS in the given message position(s) in the storage
|
||||
*
|
||||
* @param sms struct containing index array to delete
|
||||
* @return zero for success
|
||||
*/
|
||||
nsapi_error_t delete_sms(sms_info_t* sms);
|
||||
|
||||
/**
|
||||
* Internal helper methods
|
||||
*/
|
||||
nsapi_error_t list_messages();
|
||||
int read_sms_params(char *, char *);
|
||||
void free_linked_list();
|
||||
void add_info(sms_info_t* info, int index, int part_number);
|
||||
int read_udh_from_pdu(const char* pdu, sms_info_t *info, int &part_number, int &parts, int &padding_bits);
|
||||
nsapi_size_or_error_t get_data_from_pdu(const char* pdu, sms_info_t *info, int *part_number,
|
||||
char *phone_number = NULL, char *msg = NULL);
|
||||
nsapi_size_or_error_t read_pdu_payload(const char* pdu, int scheme, char *msg, int padding_bits, bool last_part);
|
||||
sms_info_t* get_oldest_sms_index();
|
||||
bool create_time(const char* time_string, time_t* time);
|
||||
int compare_time_strings(const char* time_string_1, const char* time_string_2);
|
||||
char* create_pdu(const char* phone_number, const char* message, uint8_t message_length, uint8_t msg_parts,
|
||||
uint8_t msg_part_number);
|
||||
nsapi_size_or_error_t read_sms_from_index(int msg_index, char* buf, uint16_t len, char* phone_num,
|
||||
char* time_stamp);
|
||||
nsapi_size_or_error_t read_sms(sms_info_t* sms, char* buf, char* phone_num, char* time_stamp);
|
||||
|
||||
/** Packs the given str from ascii to 7bit gsm format and converts it to hex to the given buf.
|
||||
*
|
||||
* @param str string which is to be converted
|
||||
* @param len length of the str buffer
|
||||
* @param buf preallocated buffer which holds the converted string in hex format after successful call
|
||||
* @param number_of_padding_bit padding bits needed to keep the octet boundary
|
||||
* @return length of buffer buf or zero on failure
|
||||
*/
|
||||
uint16_t pack_7_bit_gsm_and_hex(const char* str, uint16_t len, char *buf, int number_of_padding_bit);
|
||||
|
||||
/** Unpacks the given hex- and 7-bit gsm encoded str to ascii string
|
||||
*
|
||||
* @param str string which converted to ascii string to buf
|
||||
* @param len length of the str divided by two as str is hexencoded
|
||||
* @param buf preallocated destination buffer
|
||||
* @param padding_bits number of padding bits which were needed to hold the octet boundary
|
||||
* @param last_part true is last part of the encoded message
|
||||
* @return length of the destination buffer buf
|
||||
*
|
||||
*/
|
||||
uint16_t unpack_7_bit_gsm_to_str(const char* str, int len, char *buf, int padding_bits,
|
||||
bool last_part);
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
||||
#endif // AT_CELLULAR_SMS_H_
|
|
@ -0,0 +1,278 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "AT_CellularStack.h"
|
||||
#include "CellularUtil.h"
|
||||
#include "CellularLog.h"
|
||||
|
||||
using namespace mbed_cellular_util;
|
||||
using namespace mbed;
|
||||
|
||||
AT_CellularStack::AT_CellularStack(ATHandler &at, int cid, nsapi_ip_stack_t stack_type) : AT_CellularBase(at), _socket(NULL),_socket_count(0),_cid(cid), _stack_type(stack_type)
|
||||
{
|
||||
}
|
||||
|
||||
AT_CellularStack::~AT_CellularStack()
|
||||
{
|
||||
for (int i = 0; i < _socket_count; i++) {
|
||||
if (_socket[i]) {
|
||||
delete _socket[i];
|
||||
}
|
||||
}
|
||||
|
||||
delete [] _socket;
|
||||
}
|
||||
|
||||
/** NetworkStack
|
||||
*/
|
||||
|
||||
const char * AT_CellularStack::get_ip_address()
|
||||
{
|
||||
_at.lock();
|
||||
|
||||
_at.cmd_start("AT+CGPADDR=");
|
||||
_at.write_int(_cid);
|
||||
_at.cmd_stop();
|
||||
|
||||
_at.resp_start("+CGPADDR:");
|
||||
|
||||
if (_at.info_resp()) {
|
||||
|
||||
_at.skip_param();
|
||||
|
||||
int len = _at.read_string(_ip, NSAPI_IPv4_SIZE-1);
|
||||
if (len == -1) {
|
||||
_ip[0] = '\0';
|
||||
_at.unlock();
|
||||
// no IPV4 address, return
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// in case stack type is not IPV4 only, try to look also for IPV6 address
|
||||
if (_stack_type != IPV4_STACK) {
|
||||
len = _at.read_string(_ip, PDP_IPV6_SIZE-1);
|
||||
}
|
||||
}
|
||||
|
||||
_at.resp_stop();
|
||||
_at.unlock();
|
||||
|
||||
// we have at least IPV4 address
|
||||
convert_ipv6(_ip);
|
||||
|
||||
return _ip;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularStack::socket_open(nsapi_socket_t *handle, nsapi_protocol_t proto)
|
||||
{
|
||||
if (!is_protocol_supported(proto)) {
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
int max_socket_count = get_max_socket_count();
|
||||
|
||||
if (!_socket) {
|
||||
_socket = new CellularSocket*[max_socket_count];
|
||||
if (!_socket) {
|
||||
return NSAPI_ERROR_NO_SOCKET;
|
||||
}
|
||||
_socket_count = max_socket_count;
|
||||
for (int i = 0; i < max_socket_count; i++) {
|
||||
_socket[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int index = -1;
|
||||
for (int i = 0; i < max_socket_count; i++) {
|
||||
if (!_socket[i]) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (index == -1) {
|
||||
return NSAPI_ERROR_NO_SOCKET;
|
||||
}
|
||||
|
||||
// create local socket structure, socket on modem is created when app calls sendto/recvfrom
|
||||
_socket[index] = new CellularSocket;
|
||||
CellularSocket *psock;
|
||||
psock = _socket[index];
|
||||
memset(psock, 0, sizeof(CellularSocket));
|
||||
SocketAddress addr(0, get_dynamic_ip_port());
|
||||
psock->id = index;
|
||||
psock->localAddress = addr;
|
||||
psock->proto = proto;
|
||||
*handle = psock;
|
||||
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularStack::socket_close(nsapi_socket_t handle)
|
||||
{
|
||||
int err = NSAPI_ERROR_DEVICE_ERROR;
|
||||
|
||||
struct CellularSocket *socket = (struct CellularSocket *)handle;
|
||||
int sock_id = socket->id;
|
||||
int max_socket_count = get_max_socket_count();
|
||||
|
||||
int index = -1;
|
||||
for (int i = 0; i < max_socket_count; i++) {
|
||||
if (_socket[i] && _socket[i]->id == sock_id) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (index != -1) {
|
||||
_socket[index] = NULL;
|
||||
err = NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
_at.lock();
|
||||
|
||||
//_atHandler.setTimeout(...)
|
||||
|
||||
err = socket_close_impl(sock_id);
|
||||
|
||||
_at.unlock();
|
||||
|
||||
delete socket;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularStack::socket_bind(nsapi_socket_t handle, const SocketAddress &addr)
|
||||
{
|
||||
struct CellularSocket *socket = (CellularSocket *)handle;
|
||||
socket->localAddress = addr;
|
||||
|
||||
_at.lock();
|
||||
|
||||
if (!socket->created) {
|
||||
create_socket_impl(socket);
|
||||
}
|
||||
|
||||
return _at.unlock_return_error();
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularStack::socket_listen(nsapi_socket_t handle, int backlog)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularStack::socket_connect(nsapi_socket_t handle, const SocketAddress &addr)
|
||||
{
|
||||
CellularSocket *socket = (CellularSocket *)handle;
|
||||
socket->remoteAddress = addr;
|
||||
socket->connected = true;
|
||||
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularStack::socket_accept(void *server, void **socket, SocketAddress *addr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
nsapi_size_or_error_t AT_CellularStack::socket_send(nsapi_socket_t handle, const void *data, unsigned size)
|
||||
{
|
||||
CellularSocket *socket = (CellularSocket *)handle;
|
||||
if (!socket->connected) {
|
||||
return NSAPI_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
return socket_sendto(handle, socket->remoteAddress, data, size);
|
||||
}
|
||||
|
||||
nsapi_size_or_error_t AT_CellularStack::socket_sendto(nsapi_socket_t handle, const SocketAddress &addr, const void *data, unsigned size)
|
||||
{
|
||||
CellularSocket *socket = (CellularSocket *)handle;
|
||||
|
||||
nsapi_size_or_error_t ret_val = NSAPI_ERROR_OK;
|
||||
|
||||
if (!socket->created) {
|
||||
_at.lock();
|
||||
|
||||
ret_val = create_socket_impl(socket);
|
||||
|
||||
_at.unlock();
|
||||
if (ret_val != NSAPI_ERROR_OK) {
|
||||
return ret_val;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned max_packet_size = get_max_packet_size();
|
||||
|
||||
/* Check parameters */
|
||||
if (addr.get_ip_version() == NSAPI_UNSPEC ||
|
||||
size > max_packet_size) {
|
||||
return NSAPI_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
_at.lock();
|
||||
|
||||
ret_val = socket_sendto_impl(socket, addr, data, size);
|
||||
|
||||
_at.unlock();
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
nsapi_size_or_error_t AT_CellularStack::socket_recv(nsapi_socket_t handle, void *data, unsigned size)
|
||||
{
|
||||
return socket_recvfrom(handle, NULL, data, size);
|
||||
}
|
||||
|
||||
nsapi_size_or_error_t AT_CellularStack::socket_recvfrom(nsapi_socket_t handle, SocketAddress *addr, void *buffer, unsigned size)
|
||||
{
|
||||
CellularSocket *socket = (CellularSocket *)handle;
|
||||
|
||||
nsapi_size_or_error_t ret_val = NSAPI_ERROR_OK;
|
||||
|
||||
if (!socket->created) {
|
||||
_at.lock();
|
||||
|
||||
ret_val = create_socket_impl(socket);
|
||||
|
||||
_at.unlock();
|
||||
if (ret_val != NSAPI_ERROR_OK) {
|
||||
return ret_val;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned max_packet_size = get_max_packet_size();
|
||||
|
||||
/* Check parameters */
|
||||
if (size < max_packet_size) {
|
||||
log_warn("Socket receive buffer smaller than max packet size! size:%d max_packet_size:%d", size, max_packet_size);
|
||||
}
|
||||
|
||||
_at.lock();
|
||||
|
||||
ret_val = socket_recvfrom_impl(socket, addr, buffer, size);
|
||||
|
||||
_at.unlock();
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
void AT_CellularStack::socket_attach(nsapi_socket_t handle, void (*callback)(void *), void *data)
|
||||
{
|
||||
CellularSocket *socket = (CellularSocket *)handle;
|
||||
socket->_cb = callback;
|
||||
socket->_data = data;
|
||||
}
|
|
@ -0,0 +1,310 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef AT_CELLULAR_STACK_H_
|
||||
#define AT_CELLULAR_STACK_H_
|
||||
|
||||
#include "AT_CellularBase.h"
|
||||
#include "NetworkStack.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
// <PDP_addr_1> and <PDP_addr_2>: each is a string type that identifies the MT in the address space applicable to the PDP.
|
||||
// The string is given as dot-separated numeric (0-255) parameter of the form:
|
||||
// a1.a2.a3.a4 for IPv4 and
|
||||
// a1.a2.a3.a4.a5.a6.a7.a8.a9.a10.a11.a12.a13.a14.a15.a16 for IPv6.
|
||||
#define PDP_IPV6_SIZE 63+1
|
||||
|
||||
/**
|
||||
* Class AT_CellularStack.
|
||||
*
|
||||
* Implements NetworkStack and introduces interface for modem specific stack implementations.
|
||||
*/
|
||||
class AT_CellularStack : public NetworkStack, public AT_CellularBase
|
||||
{
|
||||
|
||||
public:
|
||||
AT_CellularStack(ATHandler &at, int cid, nsapi_ip_stack_t stack_type);
|
||||
virtual ~AT_CellularStack();
|
||||
|
||||
public: // NetworkStack
|
||||
|
||||
/** Get the local IP address
|
||||
*
|
||||
* @return Null-terminated representation of the local IP address
|
||||
* or null if not yet connected
|
||||
*/
|
||||
virtual const char *get_ip_address();
|
||||
|
||||
/** Opens a socket
|
||||
*
|
||||
* Creates a network socket and stores it in the specified handle.
|
||||
* The handle must be passed to following calls on the socket.
|
||||
*
|
||||
* A stack may have a finite number of sockets, in this case
|
||||
* NSAPI_ERROR_NO_SOCKET is returned if no socket is available.
|
||||
*
|
||||
* @param handle Destination for the handle to a newly created socket
|
||||
* @param proto Protocol of socket to open, NSAPI_TCP or NSAPI_UDP
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
virtual nsapi_error_t socket_open(nsapi_socket_t *handle, nsapi_protocol_t proto);
|
||||
|
||||
/** Close the socket
|
||||
*
|
||||
* Closes any open connection and deallocates any memory associated
|
||||
* with the socket.
|
||||
*
|
||||
* @param handle Socket handle
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
virtual nsapi_error_t socket_close(nsapi_socket_t handle);
|
||||
|
||||
/** Bind a specific address to a socket
|
||||
*
|
||||
* Binding a socket specifies the address and port on which to recieve
|
||||
* data. If the IP address is zeroed, only the port is bound.
|
||||
*
|
||||
* @param handle Socket handle
|
||||
* @param address Local address to bind
|
||||
* @return 0 on success, negative error code on failure.
|
||||
*/
|
||||
virtual nsapi_error_t socket_bind(nsapi_socket_t handle, const SocketAddress &address);
|
||||
|
||||
/** Listen for connections on a TCP socket
|
||||
*
|
||||
* Marks the socket as a passive socket that can be used to accept
|
||||
* incoming connections.
|
||||
*
|
||||
* @param handle Socket handle
|
||||
* @param backlog Number of pending connections that can be queued
|
||||
* simultaneously
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
virtual nsapi_error_t socket_listen(nsapi_socket_t handle, int backlog);
|
||||
|
||||
/** Connects TCP socket to a remote host
|
||||
*
|
||||
* Initiates a connection to a remote server specified by the
|
||||
* indicated address.
|
||||
*
|
||||
* @param handle Socket handle
|
||||
* @param address The SocketAddress of the remote host
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
virtual nsapi_error_t socket_connect(nsapi_socket_t handle, const SocketAddress &address);
|
||||
|
||||
/** Accepts a connection on a TCP socket
|
||||
*
|
||||
* The server socket must be bound and set to listen for connections.
|
||||
* On a new connection, creates a network socket and stores it in the
|
||||
* specified handle. The handle must be passed to following calls on
|
||||
* the socket.
|
||||
*
|
||||
* A stack may have a finite number of sockets, in this case
|
||||
* NSAPI_ERROR_NO_SOCKET is returned if no socket is available.
|
||||
*
|
||||
* This call is non-blocking. If accept would block,
|
||||
* NSAPI_ERROR_WOULD_BLOCK is returned immediately.
|
||||
*
|
||||
* @param server Socket handle to server to accept from
|
||||
* @param handle Destination for a handle to the newly created socket
|
||||
* @param address Destination for the remote address or NULL
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
virtual nsapi_error_t socket_accept(nsapi_socket_t server,
|
||||
nsapi_socket_t *handle, SocketAddress *address=0);
|
||||
|
||||
/** Send data over a TCP socket
|
||||
*
|
||||
* The socket must be connected to a remote host. Returns the number of
|
||||
* bytes sent from the buffer.
|
||||
*
|
||||
* This call is non-blocking. If send would block,
|
||||
* NSAPI_ERROR_WOULD_BLOCK is returned immediately.
|
||||
*
|
||||
* @param handle Socket handle
|
||||
* @param data Buffer of data to send to the host
|
||||
* @param size Size of the buffer in bytes
|
||||
* @return Number of sent bytes on success, negative error
|
||||
* code on failure
|
||||
*/
|
||||
virtual nsapi_size_or_error_t socket_send(nsapi_socket_t handle,
|
||||
const void *data, nsapi_size_t size);
|
||||
|
||||
/** Receive data over a TCP socket
|
||||
*
|
||||
* The socket must be connected to a remote host. Returns the number of
|
||||
* bytes received into the buffer.
|
||||
*
|
||||
* This call is non-blocking. If recv would block,
|
||||
* NSAPI_ERROR_WOULD_BLOCK is returned immediately.
|
||||
*
|
||||
* @param handle Socket handle
|
||||
* @param data Destination buffer for data received from the host
|
||||
* @param size Size of the buffer in bytes
|
||||
* @return Number of received bytes on success, negative error
|
||||
* code on failure
|
||||
*/
|
||||
virtual nsapi_size_or_error_t socket_recv(nsapi_socket_t handle,
|
||||
void *data, nsapi_size_t size);
|
||||
|
||||
/** Send a packet over a UDP socket
|
||||
*
|
||||
* Sends data to the specified address. Returns the number of bytes
|
||||
* sent from the buffer.
|
||||
*
|
||||
* This call is non-blocking. If sendto would block,
|
||||
* NSAPI_ERROR_WOULD_BLOCK is returned immediately.
|
||||
*
|
||||
* @param handle Socket handle
|
||||
* @param address The SocketAddress of the remote host
|
||||
* @param data Buffer of data to send to the host
|
||||
* @param size Size of the buffer in bytes
|
||||
* @return Number of sent bytes on success, negative error
|
||||
* code on failure
|
||||
*/
|
||||
virtual nsapi_size_or_error_t socket_sendto(nsapi_socket_t handle, const SocketAddress &address,
|
||||
const void *data, nsapi_size_t size);
|
||||
|
||||
/** Receive a packet over a UDP socket
|
||||
*
|
||||
* Receives data and stores the source address in address if address
|
||||
* is not NULL. Returns the number of bytes received into the buffer.
|
||||
*
|
||||
* This call is non-blocking. If recvfrom would block,
|
||||
* NSAPI_ERROR_WOULD_BLOCK is returned immediately.
|
||||
*
|
||||
* @param handle Socket handle
|
||||
* @param address Destination for the source address or NULL
|
||||
* @param buffer Destination buffer for data received from the host
|
||||
* @param size Size of the buffer in bytes
|
||||
* @return Number of received bytes on success, negative error
|
||||
* code on failure
|
||||
*/
|
||||
virtual nsapi_size_or_error_t socket_recvfrom(nsapi_socket_t handle, SocketAddress *address,
|
||||
void *buffer, nsapi_size_t size);
|
||||
|
||||
/** Register a callback on state change of the socket
|
||||
*
|
||||
* The specified callback will be called on state changes such as when
|
||||
* the socket can recv/send/accept successfully and on when an error
|
||||
* occurs. The callback may also be called spuriously without reason.
|
||||
*
|
||||
* The callback may be called in an interrupt context and should not
|
||||
* perform expensive operations such as recv/send calls.
|
||||
*
|
||||
* @param handle Socket handle
|
||||
* @param callback Function to call on state change
|
||||
* @param data Argument to pass to callback
|
||||
*/
|
||||
virtual void socket_attach(nsapi_socket_t handle, void (*callback)(void *), void *data);
|
||||
|
||||
protected:
|
||||
|
||||
class CellularSocket
|
||||
{
|
||||
public:
|
||||
// Socket id from cellular device
|
||||
int id;
|
||||
// Being connected means remote ip address and port are set
|
||||
bool connected;
|
||||
nsapi_protocol_t proto;
|
||||
SocketAddress remoteAddress;
|
||||
SocketAddress localAddress;
|
||||
void (*_cb)(void *);
|
||||
void *_data;
|
||||
bool created;
|
||||
bool rx_avail; // used to synchronise reading from modem
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets maximum number of sockets modem supports
|
||||
*/
|
||||
virtual int get_max_socket_count() = 0;
|
||||
|
||||
/**
|
||||
* Gets maximum packet size
|
||||
*/
|
||||
virtual int get_max_packet_size() = 0;
|
||||
|
||||
/**
|
||||
* Checks if modem supports the given protocol
|
||||
*
|
||||
* @param protocol Protocol type
|
||||
*/
|
||||
virtual bool is_protocol_supported(nsapi_protocol_t protocol) = 0;
|
||||
|
||||
/**
|
||||
* Implements modem specific AT command set for socket closing
|
||||
*
|
||||
* @param sock_id Socket id
|
||||
*/
|
||||
virtual nsapi_error_t socket_close_impl(int sock_id) = 0;
|
||||
|
||||
/**
|
||||
* Implements modem specific AT command set for creating socket
|
||||
*
|
||||
* @param socket Cellular socket handle
|
||||
*/
|
||||
virtual nsapi_error_t create_socket_impl(CellularSocket *socket) = 0;
|
||||
|
||||
/**
|
||||
* Implements modem specific AT command set for sending data
|
||||
*
|
||||
* @param socket Cellular socket handle
|
||||
* @param address The SocketAddress of the remote host
|
||||
* @param data Buffer of data to send to the host
|
||||
* @param size Size of the buffer in bytes
|
||||
* @return Number of sent bytes on success, negative error
|
||||
* code on failure
|
||||
*/
|
||||
virtual nsapi_size_or_error_t socket_sendto_impl(CellularSocket *socket, const SocketAddress &address,
|
||||
const void *data, nsapi_size_t size) = 0;
|
||||
|
||||
/**
|
||||
* Implements modem specific AT command set for receiving data
|
||||
*
|
||||
* @param socket Socket handle
|
||||
* @param address Destination for the source address or NULL
|
||||
* @param buffer Destination buffer for data received from the host
|
||||
* @param size Size of the buffer in bytes
|
||||
* @return Number of received bytes on success, negative error
|
||||
* code on failure
|
||||
*/
|
||||
virtual nsapi_size_or_error_t socket_recvfrom_impl(CellularSocket *socket, SocketAddress *address,
|
||||
void *buffer, nsapi_size_t size) = 0;
|
||||
|
||||
// socket container
|
||||
CellularSocket **_socket;
|
||||
|
||||
// number of socket slots allocated in socket container
|
||||
int _socket_count;
|
||||
|
||||
// IP address
|
||||
char _ip[PDP_IPV6_SIZE];
|
||||
|
||||
// PDP context id
|
||||
int _cid;
|
||||
|
||||
// stack type from PDP context
|
||||
nsapi_ip_stack_t _stack_type;
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
||||
#endif // AT_CELLULAR_STACK_H_
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Copyright (c) 2017, 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 CELLULAR_LIST_H_
|
||||
#define CELLULAR_LIST_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace mbed {
|
||||
|
||||
/** Class CellularList
|
||||
*
|
||||
* Templated linked list class for common usage.
|
||||
*
|
||||
*/
|
||||
template <class T> class CellularList
|
||||
{
|
||||
private:
|
||||
T *_head, *_tail;
|
||||
public:
|
||||
CellularList()
|
||||
{
|
||||
_head=NULL;
|
||||
_tail=NULL;
|
||||
}
|
||||
|
||||
T* add_new()
|
||||
{
|
||||
T *temp=new T;
|
||||
if (!temp) {
|
||||
return NULL;
|
||||
}
|
||||
temp->next = NULL;
|
||||
if (_head == NULL) {
|
||||
_head = temp;
|
||||
} else {
|
||||
_tail->next=temp;
|
||||
}
|
||||
_tail = temp;
|
||||
|
||||
return _tail;
|
||||
}
|
||||
|
||||
void delete_last()
|
||||
{
|
||||
T* previous = NULL;
|
||||
T *current=_head;
|
||||
|
||||
if (!current) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (current->next != NULL) {
|
||||
previous=current;
|
||||
current=current->next;
|
||||
}
|
||||
|
||||
if (previous) {
|
||||
_tail=previous;
|
||||
previous->next=NULL;
|
||||
} else {
|
||||
_head = NULL;
|
||||
_tail = NULL;
|
||||
}
|
||||
|
||||
delete current;
|
||||
}
|
||||
|
||||
void delete_all()
|
||||
{
|
||||
T *temp = _head;
|
||||
while (temp) {
|
||||
_head = _head->next;
|
||||
delete temp;
|
||||
temp = _head;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
T *get_head()
|
||||
{
|
||||
return _head;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
||||
#endif // CELLULAR_LIST_H_
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright (c) , 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 <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include "CellularLog.h"
|
||||
#include "us_ticker_api.h"
|
||||
#include "serial_api.h"
|
||||
#include "rtos/Mutex.h"
|
||||
|
||||
extern serial_t stdio_uart;
|
||||
extern int stdio_uart_inited;
|
||||
|
||||
namespace mbed {
|
||||
|
||||
uint32_t cellular_log_time = us_ticker_read() / 1000L;
|
||||
|
||||
/**
|
||||
* Local mutex object for synchronization
|
||||
*/
|
||||
static rtos::Mutex mutex;
|
||||
|
||||
/**
|
||||
* Lock provided for serial printing used by trace library
|
||||
*/
|
||||
static void serial_lock()
|
||||
{
|
||||
mutex.lock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Releasing lock provided for serial printing used by trace library
|
||||
*/
|
||||
static void serial_unlock()
|
||||
{
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
void log_init(PinName tx, PinName rx, int baud)
|
||||
{
|
||||
#ifdef FEATURE_COMMON_PAL
|
||||
mbed_trace_mutex_wait_function_set(serial_lock);
|
||||
mbed_trace_mutex_release_function_set(serial_unlock);
|
||||
mbed_trace_init();
|
||||
#else
|
||||
/*UARTSerial trace_serial(tx, rx, baud);
|
||||
FILE *trace = fdopen(&trace_serial, "w");*/
|
||||
serial_init(&stdio_uart, tx, rx);
|
||||
serial_baud(&stdio_uart, baud);
|
||||
stdio_uart_inited = 1;
|
||||
#endif
|
||||
log_info("\r\n\r\n**************************************");
|
||||
log_info("Hellular says Cellular Hello!");
|
||||
log_info("Build time %s %s", __DATE__, __TIME__);
|
||||
}
|
||||
} // namespace mbed
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright (c) 2017, 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 CELLULAR_LOG_H_
|
||||
#define CELLULAR_LOG_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#ifdef FEATURE_COMMON_PAL
|
||||
#include <stdarg.h>
|
||||
#endif // FEATURE_COMMON_PAL
|
||||
#include "PinNames.h"
|
||||
#include "us_ticker_api.h"
|
||||
#include "mbed_debug.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
/** this print is some deep information for debug purpose */
|
||||
#define TRACE_LEVEL_DEBUG 0x10
|
||||
/** Info print, for general purpose prints */
|
||||
#define TRACE_LEVEL_INFO 0x08
|
||||
/** warning prints, which shouldn't causes any huge problems */
|
||||
#define TRACE_LEVEL_WARN 0x04
|
||||
/** Error prints, which causes probably problems, e.g. out of mem. */
|
||||
#define TRACE_LEVEL_ERROR 0x02
|
||||
/** special level for cmdline. Behaviours like "plain mode" */
|
||||
#define TRACE_LEVEL_CMD 0x01
|
||||
|
||||
#define TRACE_GROUP "cellular"
|
||||
|
||||
#ifndef MBED_TRACE_MAX_LEVEL
|
||||
#define MBED_TRACE_MAX_LEVEL TRACE_LEVEL_ERROR
|
||||
#endif
|
||||
|
||||
#ifdef FEATURE_COMMON_PAL
|
||||
#include "mbed-trace/mbed_trace.h"
|
||||
#define log_debug tr_debug
|
||||
#define log_info tr_info
|
||||
#define log_warn tr_warn
|
||||
#define log_error tr_error
|
||||
#else
|
||||
extern uint32_t cellular_log_time;
|
||||
#if (MBED_TRACE_MAX_LEVEL >= TRACE_LEVEL_DEBUG)
|
||||
#define log_debug(format, ...) do { debug("DEBUG" " [" TRACE_GROUP " %ums] " format "\r\n", (us_ticker_read()-cellular_log_time) / 1000L, ## __VA_ARGS__); } while (0)
|
||||
#else
|
||||
#define log_debug(...)
|
||||
#endif
|
||||
#if (MBED_TRACE_MAX_LEVEL >= TRACE_LEVEL_INFO)
|
||||
#define log_info(format, ...) do { debug("INFO" " [" TRACE_GROUP " %ums] " format "\r\n", (us_ticker_read()-cellular_log_time) / 1000L, ## __VA_ARGS__); } while (0)
|
||||
#else
|
||||
#define log_info(...)
|
||||
#endif
|
||||
#if (MBED_TRACE_MAX_LEVEL >= TRACE_LEVEL_WARN)
|
||||
#define log_warn(format, ...) do { debug("WARN" " [" TRACE_GROUP " %ums] " format "\r\n", (us_ticker_read()-cellular_log_time) / 1000L, ## __VA_ARGS__); } while (0)
|
||||
#else
|
||||
#define log_warn(...)
|
||||
#endif
|
||||
#if (MBED_TRACE_MAX_LEVEL >= TRACE_LEVEL_ERROR)
|
||||
#define log_error(format, ...) do { debug("ERROR" " [" TRACE_GROUP " %ums] " format "\r\n", (us_ticker_read()-cellular_log_time) / 1000L, ## __VA_ARGS__); } while (0)
|
||||
#else
|
||||
#define log_error(...)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
extern void log_init(PinName tx, PinName rx, int baud);
|
||||
|
||||
} // namespace mbed
|
||||
|
||||
#endif // CELLULAR_LOG_H_
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 2017, 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 CELLULAR_TARGETS_H_
|
||||
#define CELLULAR_TARGETS_H_
|
||||
|
||||
namespace mbed {
|
||||
|
||||
#define UART 1
|
||||
#define MUX 2
|
||||
|
||||
#ifndef CELLULAR_DEVICE
|
||||
#if defined(TARGET_ADV_WISE_1570) || defined(TARGET_MTB_ADV_WISE_1570)
|
||||
#define CELLULAR_DEVICE QUECTEL_BC95
|
||||
#elif TARGET_MTS_DRAGONFLY_F411RE
|
||||
#define CELLULAR_DEVICE TELIT_HE910
|
||||
#elif TARGET_MTB_MTS_DRAGONFLY
|
||||
#define CELLULAR_DEVICE TELIT_HE910
|
||||
#elif TARGET_UBLOX_C030
|
||||
#define CELLULAR_DEVICE UBLOX_C027
|
||||
#elif TARGET_UBLOX_C027
|
||||
#define CELLULAR_DEVICE UBLOX_C027
|
||||
|
||||
#else
|
||||
#error Cellular target not defined, see cellular/targets.h
|
||||
//#define CELLULAR_TARGET <target-modem>
|
||||
//#define MDMTXD <pin-name>
|
||||
//#define MDMRXD <pin-name>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
} // namespace mbed
|
||||
#endif // CELLULAR_TARGETS_H_
|
|
@ -0,0 +1,326 @@
|
|||
/*
|
||||
* Copyright (c) , 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 "CellularUtil.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace mbed_cellular_util {
|
||||
|
||||
void convert_ipv6(char* ip)
|
||||
{
|
||||
if (!ip) {
|
||||
return;
|
||||
}
|
||||
|
||||
int len = strlen(ip);
|
||||
int pos = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (ip[i] == '.') {
|
||||
pos++;
|
||||
}
|
||||
if (pos > 3) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// more that 3 periods mean that it was ipv6 but in format of a1.a2.a3.a4.a5.a6.a7.a8.a9.a10.a11.a12.a13.a14.a15.a16
|
||||
// we need to convert it to hexadecimal format separated with colons
|
||||
if (pos > 3) {
|
||||
pos = 0;
|
||||
int ip_pos = 0;
|
||||
char b;
|
||||
bool set_colon = false;
|
||||
for (i = 0; i < len; i++) {
|
||||
if (ip[i] == '.') {
|
||||
b = (char)strtol (ip+ip_pos, NULL, 10); // convert to char to int so we can change it to hex string
|
||||
pos += char_str_to_hex_str(&b, 1, ip+pos, !set_colon); // omit leading zeroes with using set_colon flag
|
||||
if (set_colon) {
|
||||
ip[pos++] = ':';
|
||||
set_colon = false;
|
||||
} else {
|
||||
set_colon = true;
|
||||
}
|
||||
ip_pos = i+1; // skip the '.'
|
||||
}
|
||||
|
||||
// handle the last part which does not end with '.' but '\0'
|
||||
if (i == len -1) {
|
||||
b = (char)strtol(ip+ip_pos, NULL, 10);
|
||||
pos += char_str_to_hex_str(&b, 1, ip+pos, !set_colon);
|
||||
ip[pos] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For example "32.1.13.184.0.0.205.48.0.0.0.0.0.0.0.0"
|
||||
void separate_ip4like_addresses(char* orig, char* ip, size_t ip_size, char* ip2, size_t ip2_size)
|
||||
{
|
||||
// ipv4-like notation
|
||||
int len = strlen(orig);
|
||||
int count = 0, i = 0, pos = 0;
|
||||
char *temp;
|
||||
|
||||
for (; i < len; i++) {
|
||||
if (orig[i] == '.') {
|
||||
count++;
|
||||
if (count == 4) {
|
||||
pos = i;
|
||||
} else if (count == 16) {
|
||||
pos = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count == 3) { // normal ipv4, copy to ip
|
||||
if (ip_size > strlen(orig)) {
|
||||
memcpy(ip, orig, strlen(orig));
|
||||
ip[strlen(orig)] = '\0';
|
||||
} else {
|
||||
ip[0] = '\0';
|
||||
}
|
||||
if (ip2) {
|
||||
ip2[0] = '\0';
|
||||
}
|
||||
} else if (count == 7) { // ipv4 and subnet mask. Need to separate those.
|
||||
temp = &orig[pos];
|
||||
if ((uint8_t)ip_size > temp-orig) {
|
||||
memcpy(ip, orig, temp-orig);
|
||||
ip[temp-orig] = '\0';
|
||||
}
|
||||
temp++; // skip the '.'
|
||||
if (ip2 && (ip2_size > strlen(temp))) {
|
||||
memcpy(ip2, temp, strlen(temp));
|
||||
ip2[strlen(temp)] = '\0';
|
||||
}
|
||||
} else if (count == 15) { // only one ipv6 address in ipv4-like notation
|
||||
if (ip_size > strlen(orig)) {
|
||||
memcpy(ip, orig, strlen(orig));
|
||||
ip[strlen(orig)] = '\0';
|
||||
convert_ipv6(ip);
|
||||
} else {
|
||||
ip[0] = '\0';
|
||||
}
|
||||
if (ip2) {
|
||||
ip2[0] = '\0';
|
||||
}
|
||||
} else if (count == 31){ // ipv6 + ipv6subnet mask in ipv4-like notation separated by dot '.'
|
||||
temp = &orig[pos];
|
||||
if ((uint8_t)ip_size > temp-orig) {
|
||||
memcpy(ip, orig, temp-orig);
|
||||
ip[temp-orig] = '\0';
|
||||
convert_ipv6(ip);
|
||||
}
|
||||
temp++; // skip the '.'
|
||||
if (ip2 && (ip2_size > strlen(temp))) {
|
||||
memcpy(ip2, temp, strlen(temp));
|
||||
ip2[strlen(temp)] = '\0';
|
||||
convert_ipv6(ip2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void separate_ip_addresses(char* orig, char* ip, size_t ip_size, char* ip2, size_t ip2_size)
|
||||
{
|
||||
// orig can include ipv4, ipv6, both or two ip4/ipv6 addresses.
|
||||
// also format depends on possible AT+CGPIAF
|
||||
if (!orig || !ip) {
|
||||
if (ip) {
|
||||
ip[0] = '\0';
|
||||
}
|
||||
if (ip2) {
|
||||
ip2[0] = '\0';
|
||||
}
|
||||
return;
|
||||
}
|
||||
// 1. try to found ':'. If it's found then we know that possible addresses are separated with space
|
||||
char *temp;
|
||||
temp = strchr(orig, ':');
|
||||
|
||||
if (temp != NULL) {
|
||||
// found ':'
|
||||
temp = strstr(orig, " ");
|
||||
// found space as separator and it wasn't in beginning --> contains 2 ip addresses
|
||||
if (temp && temp != orig) {
|
||||
if ((uint8_t)ip_size > temp-orig) {
|
||||
memcpy(ip, orig, temp-orig);
|
||||
ip[temp-orig] = '\0';
|
||||
} else {
|
||||
ip[0] = '\0';
|
||||
}
|
||||
temp++; // skip the space
|
||||
if (ip2 && (ip2_size > strlen(temp))) {
|
||||
memcpy(ip2, temp, strlen(temp));
|
||||
ip2[strlen(temp)] = '\0';
|
||||
} else {
|
||||
ip2[0] = '\0';
|
||||
}
|
||||
} else {
|
||||
// Space was the first char or no space found ---> only one ip, copy to ip
|
||||
size_t size = strlen(orig);
|
||||
if (temp) {
|
||||
size = strlen(temp);
|
||||
}
|
||||
|
||||
if (ip_size > size) {
|
||||
memcpy(ip, orig, size);
|
||||
ip[size] = '\0';
|
||||
} else {
|
||||
ip[0] = '\0';
|
||||
}
|
||||
if (ip2) {
|
||||
ip2[0] = '\0';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
temp = strstr(orig, " ");
|
||||
// found space as separator and it wasn't in beginning --> contains 2 ip addresses
|
||||
if (temp && temp != orig) {
|
||||
separate_ip4like_addresses(temp++, ip2, ip2_size, NULL, 0);
|
||||
orig[temp-orig-1] = '\0';
|
||||
separate_ip4like_addresses(orig, ip, ip_size, NULL, 0);
|
||||
orig[temp-orig-1] = ' '; // put space back to keep orig as original
|
||||
}
|
||||
else {
|
||||
separate_ip4like_addresses(orig, ip, ip_size, ip2, ip2_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void prefer_ipv6(char* ip, size_t ip_size, char* ip2, size_t ip2_size)
|
||||
{
|
||||
if (!ip || !ip2) {
|
||||
return;
|
||||
}
|
||||
// assume that that ipv6 is already in formatted to use ':'
|
||||
// 1. try to found ':'. If it's found then we know that this is ipv6
|
||||
char *temp;
|
||||
temp = strchr(ip, ':');
|
||||
if (temp) {
|
||||
// ip has ipv6 address, we can leave
|
||||
return;
|
||||
} else {
|
||||
// ip was not ipv6, check if ip2 is
|
||||
temp = strchr(ip2, ':');
|
||||
if (temp) {
|
||||
// ipv6 was found in ip2 but not in ip ---> we must swap them. Sadly ip and ip2 might not be pointers
|
||||
// so we can't just swap them, must use copy.
|
||||
if (strlen(ip) < ip2_size && strlen(ip2) < ip_size && strlen(ip) < 64) {
|
||||
char tmp[64];
|
||||
strncpy(tmp, ip, strlen(ip));
|
||||
tmp[strlen(ip)] = '\0';
|
||||
strncpy(ip, ip2, strlen(ip2));
|
||||
ip[strlen(ip2)] = '\0';
|
||||
strncpy(ip2, tmp, strlen(tmp));
|
||||
ip2[strlen(tmp)] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void int_to_hex_str(uint8_t num, char* buf)
|
||||
{
|
||||
char charNum = num;
|
||||
char_str_to_hex_str(&charNum, 1, buf);
|
||||
}
|
||||
|
||||
int hex_str_to_int(const char *hex_string, int hex_string_length)
|
||||
{
|
||||
const int base = 16;
|
||||
int character_as_integer, integer_output = 0;
|
||||
|
||||
for (int i=0;i<hex_string_length && hex_string[i] != '\0';i++) {
|
||||
if (hex_string[i] >= '0' && hex_string[i] <= '9') {
|
||||
character_as_integer = hex_string[i] - '0';
|
||||
} else if (hex_string[i] >= 'A' && hex_string[i] <= 'F') {
|
||||
character_as_integer = hex_string[i] - 'A' + 10;
|
||||
} else {
|
||||
character_as_integer = hex_string[i] - 'a' + 10;
|
||||
}
|
||||
integer_output *= base;
|
||||
integer_output += character_as_integer;
|
||||
}
|
||||
|
||||
return integer_output;
|
||||
}
|
||||
|
||||
int hex_str_to_char_str(const char* str, uint16_t len, char *buf)
|
||||
{
|
||||
int strcount = 0;
|
||||
for (int i = 0; i+1 < len; i += 2) {
|
||||
int upper = hex_str_to_int(str+i, 1);
|
||||
int lower = hex_str_to_int(str+i+1, 1);
|
||||
buf[strcount] = ((upper<<4) & 0xF0) | (lower & 0x0F);
|
||||
strcount++;
|
||||
}
|
||||
|
||||
return strcount;
|
||||
}
|
||||
|
||||
void uint_to_binary_str(uint32_t num, char* str, int str_size, int bit_cnt)
|
||||
{
|
||||
if (!str || str_size < bit_cnt) {
|
||||
return;
|
||||
}
|
||||
int tmp, pos = 0;
|
||||
|
||||
for (int i = 31; i >= 0; i--) {
|
||||
tmp = num >> i;
|
||||
if (i < bit_cnt) {
|
||||
if (tmp&1) {
|
||||
str[pos] = 1 + '0';
|
||||
} else {
|
||||
str[pos] = 0 + '0';
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int char_str_to_hex_str(const char* str, uint16_t len, char *buf, bool omit_leading_zero)
|
||||
{
|
||||
if (!str || !buf) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *ptr = buf;
|
||||
int i=0;
|
||||
while (i < len) {
|
||||
if (omit_leading_zero == true && i == 0 && !(str[i]>>4 & 0x0F)) {
|
||||
*ptr++ = hex_values[(str[i]) & 0x0F];
|
||||
} else {
|
||||
*ptr++ = hex_values[((str[i])>>4) & 0x0F];
|
||||
*ptr++ = hex_values[(str[i]) & 0x0F];
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return ptr-buf;
|
||||
}
|
||||
|
||||
uint16_t get_dynamic_ip_port()
|
||||
{
|
||||
static uint16_t port;
|
||||
port++;
|
||||
if (port < 49152) {
|
||||
port = 49152;
|
||||
}
|
||||
return port;
|
||||
}
|
||||
|
||||
} // namespace mbed_cellular_util
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* Copyright (c) 2017, 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 CELLULAR_UTIL_H_
|
||||
#define CELLULAR_UTIL_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace mbed_cellular_util {
|
||||
|
||||
// some helper macros
|
||||
#define EMPTY_CHECK(val) (val ## 1)
|
||||
#define EMPTY(val) (EMPTY_CHECK(val) == 1)
|
||||
#define _CELLULAR_STRINGIFY(a) #a
|
||||
#define CELLULAR_STRINGIFY(a) _CELLULAR_STRINGIFY(a)
|
||||
|
||||
static const char hex_values[] = "0123456789ABCDEF";
|
||||
|
||||
/** Converts the given ip address to proper IPv6 address if needed.
|
||||
* Conversion is done only if it's NOT IPv4 and separated with colons.
|
||||
* AT command +CGPADDR can give IP address in format of a1.a2.a3.a4.a5.a6.a7.a8.a9.a10.a11.a12.a13.a14.a15.a16 for IPv6
|
||||
* where ax are in decimal format. In this case function converts decimals to hex with separated with colons.
|
||||
*
|
||||
* @param ip ip address which can be IPv4 or IPv6 in different formats from AT command +CGPADDR. Converted result uses same buffer.
|
||||
*/
|
||||
void convert_ipv6(char* ip);
|
||||
|
||||
/** Separates ip addresses from the given 'orig' string. 'orig' may contain zero, one or two ip addresses in various formats.
|
||||
* See AT command +CGPIAF from 3GPP TS 27.007 for details. Does also needed conversions for ipv6 addresses.
|
||||
*
|
||||
* @param orig original string which contains zero, one or two ip addressees in various formats
|
||||
* @param ip preallocated buffer which might contain ip address after return
|
||||
* @param ip_size size of preallocated buffer ip
|
||||
* @param ip2 preallocated buffer which might contain ip address after return
|
||||
* @param ip2_size size of preallocated buffer ip2
|
||||
*
|
||||
*/
|
||||
void separate_ip_addresses(char* orig, char* ip, size_t ip_size, char* ip2, size_t ip2_size);
|
||||
|
||||
/** Swaps the arrays if param ip does not contain ipv6 address but param ip2 does.
|
||||
*
|
||||
* @param ip ip address
|
||||
* @param ip_size size of buffer ip
|
||||
* @param ip2 ip address
|
||||
* @param ip2_size size of buffer ip2
|
||||
*/
|
||||
void prefer_ipv6(char* ip, size_t ip_size, char* ip2, size_t ip2_size);
|
||||
|
||||
/** Converts the given int to two hex characters
|
||||
*
|
||||
* @param num number to be converted to hex string
|
||||
* @param buf preallocated buffer which will contain 2 char length hex value
|
||||
*/
|
||||
void int_to_hex_str(uint8_t num, char* buf);
|
||||
|
||||
/** Converts the given buffer 'str' to hex buffer 'buf. First 'len' char's are converted to two hex bytes.
|
||||
*
|
||||
* @param str char buffer which is to be converted to hex
|
||||
* @param len how many chars from str are to be converted
|
||||
* @param buf destination buffer for hex converted chars. Buffer should be double the size of str to fit hex-encoded string.
|
||||
* @param omit_leading_zero if true then possible leading zeroes are omitted
|
||||
*/
|
||||
int char_str_to_hex_str(const char* str, uint16_t len, char *buf, bool omit_leading_zero = false);
|
||||
|
||||
/** Converts the given hex string to integer
|
||||
*
|
||||
* @param hex_string hex string from where chars are converted to int
|
||||
* @param hex_string_length length of the param hex_string
|
||||
* @return hex_string converted to int
|
||||
*/
|
||||
int hex_str_to_int(const char *hex_string, int hex_string_length);
|
||||
|
||||
/** Converts the given hex string str to char string to buf
|
||||
*
|
||||
* @param str hex string which is converted to char string to buf
|
||||
* @param len length of the param str/how many hex are converted
|
||||
* @param buf preallocated buffer where result conversion is stored
|
||||
* @return length of the buf
|
||||
*/
|
||||
int hex_str_to_char_str(const char* str, uint16_t len, char *buf);
|
||||
|
||||
/** Converts the given uint to binary string. Fills the given str starting from [0] with the number of bits defined by bit_cnt
|
||||
* For example uint_to_binary_string(9, str, 10) would fill str "0000001001"
|
||||
* For example uint_to_binary_string(9, str, 3) would fill str "001"
|
||||
*
|
||||
* @param num uint to converts to binary string
|
||||
* @param str buffer for converted binary string
|
||||
* @param str_size size of the str buffer
|
||||
* @param bit_cnt defines how many bits are filled to buffer started from lsb
|
||||
*/
|
||||
void uint_to_binary_str(uint32_t num, char* str, int str_size, int bit_cnt);
|
||||
|
||||
/** Get dynamic port for socket
|
||||
*
|
||||
* @return next port number above 49152
|
||||
*/
|
||||
uint16_t get_dynamic_ip_port();
|
||||
|
||||
} // namespace mbed_cellular_util
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,565 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2017, 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 MUX_H
|
||||
#define MUX_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "FileHandle.h"
|
||||
#include "PlatformMutex.h"
|
||||
#include "Semaphore.h"
|
||||
#include "EventQueue.h"
|
||||
|
||||
#define MUX_DLCI_INVALID_ID 0 /* Invalid DLCI ID. Used to invalidate MuxDataService object. */
|
||||
#define MUX_CRC_TABLE_LEN 256u /* CRC table length in number of bytes. */
|
||||
|
||||
#ifndef MBED_CONF_MUX_DLCI_COUNT
|
||||
#define MBED_CONF_MUX_DLCI_COUNT 3u /* Number of supported DLCI IDs. */
|
||||
#endif
|
||||
#ifndef MBED_CONF_MUX_BUFFER_SIZE
|
||||
#define MBED_CONF_MUX_BUFFER_SIZE 31u /* Size of TX/Rx buffers in number of bytes. */
|
||||
#endif
|
||||
|
||||
/* More RAM needs to allocated if more than 4 DLCI ID to be supported see @ref tx_callback_context for details. */
|
||||
MBED_STATIC_ASSERT(MBED_CONF_MUX_DLCI_COUNT <= 4u, "");
|
||||
|
||||
|
||||
/* @todo:
|
||||
I assume that we need to export some kind of #defines for EVENT_SIZE and MAX_EVENT_COUNT (max number of events that can
|
||||
be queued at the same time by the module inside EventQueue, so that the application designer can calculate the RAM
|
||||
storage requirements correctly at compile time.
|
||||
*/
|
||||
|
||||
namespace mbed {
|
||||
|
||||
class MuxDataService : public FileHandle
|
||||
{
|
||||
friend class Mux;
|
||||
public:
|
||||
|
||||
/** Enqueue user data for transmission.
|
||||
*
|
||||
* @note: This is API is only meant to be used for the multiplexer (user) data service tx. Supplied buffer can be
|
||||
* reused/freed upon call return.
|
||||
*
|
||||
* @param buffer Begin of the user data.
|
||||
* @param size The number of bytes to write.
|
||||
* @return The number of bytes written.
|
||||
*/
|
||||
virtual ssize_t write(const void* buffer, size_t size);
|
||||
|
||||
/** Read user data into a buffer.
|
||||
*
|
||||
* @note: This is API is only meant to be used for the multiplexer (user) data service rx.
|
||||
*
|
||||
* @param buffer The buffer to read in to.
|
||||
* @param size The number of bytes to read.
|
||||
* @return The number of bytes read, -EAGAIN if no data available for read.
|
||||
*/
|
||||
virtual ssize_t read(void *buffer, size_t size);
|
||||
|
||||
/** Not supported by the implementation. */
|
||||
virtual off_t seek(off_t offset, int whence = SEEK_SET);
|
||||
|
||||
/** Not supported by the implementation. */
|
||||
virtual int close();
|
||||
|
||||
/** Register a callback on completion of enqueued write and read operations.
|
||||
*
|
||||
* @note: The registered callback is called within thread context supplied in eventqueue_attach.
|
||||
*
|
||||
* @param func Function to call upon event generation.
|
||||
*/
|
||||
virtual void sigio(Callback<void()> func);
|
||||
|
||||
/** Constructor. */
|
||||
MuxDataService() : _dlci(MUX_DLCI_INVALID_ID) {};
|
||||
|
||||
private:
|
||||
|
||||
/* Deny copy constructor. */
|
||||
MuxDataService(const MuxDataService& obj);
|
||||
|
||||
/* Deny assignment operator. */
|
||||
MuxDataService& operator=(const MuxDataService& obj);
|
||||
|
||||
uint8_t _dlci; /* DLCI number. Valid range 1 - 63. */
|
||||
Callback<void()> _sigio_cb; /* Registered signal callback. */
|
||||
};
|
||||
|
||||
|
||||
class Mux
|
||||
{
|
||||
friend class MuxDataService;
|
||||
public:
|
||||
|
||||
/* Definition for multiplexer establishment status type. */
|
||||
enum MuxEstablishStatus {
|
||||
MUX_ESTABLISH_SUCCESS = 0, /* Peer accepted the request. */
|
||||
MUX_ESTABLISH_REJECT, /* Peer rejected the request. */
|
||||
MUX_ESTABLISH_TIMEOUT, /* Timeout occurred for the request. */
|
||||
MUX_ESTABLISH_MAX /* Enumeration upper bound. */
|
||||
};
|
||||
|
||||
/* @ref MuxEstablishStatus type assigned to _shared_memory variable, which has sizeof(uint8_t) storage class. Enforce
|
||||
expected behaviour compile time. */
|
||||
MBED_STATIC_ASSERT(sizeof(MuxEstablishStatus) == sizeof(uint8_t), "");
|
||||
|
||||
/* Definition for multiplexer establishment return code type. */
|
||||
enum MuxReturnStatus {
|
||||
MUX_STATUS_SUCCESS = 0,
|
||||
MUX_STATUS_INPROGRESS,
|
||||
MUX_STATUS_INVALID_RANGE,
|
||||
MUX_STATUS_MUX_NOT_OPEN,
|
||||
MUX_STATUS_NO_RESOURCE,
|
||||
MUX_STATUS_MAX
|
||||
};
|
||||
|
||||
/** Module init. */
|
||||
static void module_init();
|
||||
|
||||
/** Establish the multiplexer control channel.
|
||||
*
|
||||
* @note: Relevant request specific parameters are fixed at compile time within multiplexer component.
|
||||
* @note: Call returns when response from the peer is received, timeout or write error occurs.
|
||||
*
|
||||
* @param status Operation completion code.
|
||||
*
|
||||
* @return MUX_STATUS_SUCCESS Operation completed, check status for completion code.
|
||||
* @return MUX_STATUS_INPROGRESS Operation not started, control channel open already in progress.
|
||||
* @return MUX_STATUS_NO_RESOURCE Operation not started, multiplexer control channel already open.
|
||||
*/
|
||||
static MuxReturnStatus mux_start(MuxEstablishStatus &status);
|
||||
|
||||
/** Establish a DLCI.
|
||||
*
|
||||
* @note: Relevant request specific parameters are fixed at compile time within multiplexer component.
|
||||
* @note: Call returns when response from the peer is received or timeout occurs.
|
||||
*
|
||||
* @warning: Not allowed to be called from callback context.
|
||||
*
|
||||
* @param dlci_id ID of the DLCI to establish. Valid range 1 - 63.
|
||||
* @param status Operation completion code.
|
||||
* @param obj Valid object upon status having MUX_ESTABLISH_SUCCESS, NULL upon failure.
|
||||
*
|
||||
* @return MUX_STATUS_SUCCESS Operation completed, check status for completion code.
|
||||
* @return MUX_STATUS_INPROGRESS Operation not started, DLCI establishment already in progress.
|
||||
* @return MUX_STATUS_INVALID_RANGE Operation not started, DLCI ID not in valid range.
|
||||
* @return MUX_STATUS_MUX_NOT_OPEN Operation not started, no established multiplexer control channel exists.
|
||||
* @return MUX_STATUS_NO_RESOURCE Operation not started, dlci_id, or all available DLCI ID resources,
|
||||
* already in use.
|
||||
*/
|
||||
static MuxReturnStatus dlci_establish(uint8_t dlci_id, MuxEstablishStatus &status, FileHandle **obj);
|
||||
|
||||
/** Attach serial interface to the object.
|
||||
*
|
||||
* @param serial Serial interface to be used.
|
||||
*/
|
||||
static void serial_attach(FileHandle *serial);
|
||||
|
||||
/** Attach EventQueue interface to the object.
|
||||
*
|
||||
* @param event_queue Event queue interface to be used.
|
||||
*/
|
||||
static void eventqueue_attach(events::EventQueue *event_queue);
|
||||
|
||||
private:
|
||||
|
||||
/* Definition for Rx event type. */
|
||||
enum RxEvent {
|
||||
RX_READ = 0,
|
||||
RX_RESUME,
|
||||
RX_EVENT_MAX
|
||||
};
|
||||
|
||||
/* Definition for Tx state machine. */
|
||||
enum TxState {
|
||||
TX_IDLE = 0,
|
||||
TX_RETRANSMIT_ENQUEUE,
|
||||
TX_RETRANSMIT_DONE,
|
||||
TX_INTERNAL_RESP,
|
||||
TX_NORETRANSMIT,
|
||||
TX_STATE_MAX
|
||||
};
|
||||
|
||||
/* Definition for Rx state machine. */
|
||||
enum RxState {
|
||||
RX_FRAME_START = 0,
|
||||
RX_HEADER_READ,
|
||||
RX_TRAILER_READ,
|
||||
RX_SUSPEND,
|
||||
RX_STATE_MAX
|
||||
};
|
||||
|
||||
/* Definition for frame type within rx path. */
|
||||
enum FrameRxType {
|
||||
FRAME_RX_TYPE_SABM = 0,
|
||||
FRAME_RX_TYPE_UA,
|
||||
FRAME_RX_TYPE_DM,
|
||||
FRAME_RX_TYPE_DISC,
|
||||
FRAME_RX_TYPE_UIH,
|
||||
FRAME_RX_TYPE_NOT_SUPPORTED,
|
||||
FRAME_RX_TYPE_MAX
|
||||
};
|
||||
|
||||
/* Definition for frame type within tx path. */
|
||||
enum FrameTxType {
|
||||
FRAME_TX_TYPE_SABM = 0,
|
||||
FRAME_TX_TYPE_DM,
|
||||
FRAME_TX_TYPE_UIH,
|
||||
FRAME_TX_TYPE_MAX
|
||||
};
|
||||
|
||||
/** Registered time-out expiration event. */
|
||||
static void on_timeout();
|
||||
|
||||
/** Registered deferred call event in safe (thread context) supplied in eventqueue_attach. */
|
||||
static void on_deferred_call();
|
||||
|
||||
/** Registered sigio callback from FileHandle. */
|
||||
static void on_sigio();
|
||||
|
||||
/** Calculate fcs.
|
||||
*
|
||||
* @param buffer Input buffer.
|
||||
* @param input_len Input length in number of bytes.
|
||||
*
|
||||
* @return Calculated fcs.
|
||||
*/
|
||||
static uint8_t fcs_calculate(const uint8_t *buffer, uint8_t input_len);
|
||||
|
||||
/** Construct sabm request message.
|
||||
*
|
||||
* @param dlci_id ID of the DLCI to establish
|
||||
*/
|
||||
static void sabm_request_construct(uint8_t dlci_id);
|
||||
|
||||
/** Construct dm response message.
|
||||
*/
|
||||
static void dm_response_construct();
|
||||
|
||||
/** Construct user information frame.
|
||||
*
|
||||
* @param dlci_id ID of the DLCI to establish
|
||||
* @param buffer
|
||||
* @param size
|
||||
*/
|
||||
static void user_information_construct(uint8_t dlci_id, const void *buffer, size_t size);
|
||||
|
||||
/** Do write operation if pending data available.
|
||||
*/
|
||||
static void write_do();
|
||||
|
||||
/** Generate Rx event.
|
||||
*
|
||||
* @param event Rx event
|
||||
*/
|
||||
static void rx_event_do(RxEvent event);
|
||||
|
||||
/** Rx event frame start read state.
|
||||
*
|
||||
* @return Number of bytes read, -EAGAIN if no data available.
|
||||
*/
|
||||
static ssize_t on_rx_read_state_frame_start();
|
||||
|
||||
/** Rx event header read state.
|
||||
*
|
||||
* @return Number of bytes read, -EAGAIN if no data available.
|
||||
*/
|
||||
static ssize_t on_rx_read_state_header_read();
|
||||
|
||||
/** Rx event trailer read state.
|
||||
*
|
||||
* @return Number of bytes read, -EAGAIN if no data available.
|
||||
*/
|
||||
static ssize_t on_rx_read_state_trailer_read();
|
||||
|
||||
/** Rx event suspend read state.
|
||||
*
|
||||
* @return Number of bytes read, -EAGAIN if no data available.
|
||||
*/
|
||||
static ssize_t on_rx_read_state_suspend();
|
||||
|
||||
/** Process received SABM frame. */
|
||||
static void on_rx_frame_sabm();
|
||||
|
||||
/** Process received UA frame. */
|
||||
static void on_rx_frame_ua();
|
||||
|
||||
/** Process received DM frame. */
|
||||
static void on_rx_frame_dm();
|
||||
|
||||
/** Process received DISC frame. */
|
||||
static void on_rx_frame_disc();
|
||||
|
||||
/** Process received UIH frame. */
|
||||
static void on_rx_frame_uih();
|
||||
|
||||
/** Process received frame, which is not supported. */
|
||||
static void on_rx_frame_not_supported();
|
||||
|
||||
/** Process valid received frame. */
|
||||
static void valid_rx_frame_decode();
|
||||
|
||||
/** SABM frame tx path post processing. */
|
||||
static void on_post_tx_frame_sabm();
|
||||
|
||||
/** DM frame tx path post processing. */
|
||||
static void on_post_tx_frame_dm();
|
||||
|
||||
/** UIH frame tx path post processing. */
|
||||
static void on_post_tx_frame_uih();
|
||||
|
||||
/** Resolve rx frame type.
|
||||
*
|
||||
* @return Frame type.
|
||||
*/
|
||||
static Mux::FrameRxType frame_rx_type_resolve();
|
||||
|
||||
/** Resolve tx frame type.
|
||||
*
|
||||
* @return Frame type.
|
||||
*/
|
||||
static Mux::FrameTxType frame_tx_type_resolve();
|
||||
|
||||
/** Begin the frame retransmit sequence. */
|
||||
static void frame_retransmit_begin();
|
||||
|
||||
/** TX state entry functions. */
|
||||
static void tx_retransmit_enqueu_entry_run();
|
||||
static void tx_retransmit_done_entry_run();
|
||||
static void tx_idle_entry_run();
|
||||
static void tx_internal_resp_entry_run();
|
||||
static void tx_noretransmit_entry_run();
|
||||
typedef void (*tx_state_entry_func_t)();
|
||||
|
||||
/** TX state exit function. */
|
||||
static void tx_idle_exit_run();
|
||||
typedef void (*tx_state_exit_func_t)();
|
||||
|
||||
/** Change Tx state machine state.
|
||||
*
|
||||
* @param new_state State to transit.
|
||||
* @param entry_func State entry function.
|
||||
* @param exit_func State exit function.
|
||||
*/
|
||||
static void tx_state_change(TxState new_state, tx_state_entry_func_t entry_func, tx_state_exit_func_t exit_func);
|
||||
|
||||
/** RX state entry functions. */
|
||||
static void rx_header_read_entry_run();
|
||||
typedef void (*rx_state_entry_func_t)();
|
||||
|
||||
/** Null action function. */
|
||||
static void null_action();
|
||||
|
||||
/** Change Rx state machine state.
|
||||
*
|
||||
* @param new_state State to transit.
|
||||
* @param entry_func State entry function.
|
||||
*/
|
||||
static void rx_state_change(RxState new_state, rx_state_entry_func_t entry_func);
|
||||
|
||||
/** Begin DM frame transmit sequence. */
|
||||
static void dm_response_send();
|
||||
|
||||
/** Append DLCI ID to storage.
|
||||
*
|
||||
* @param dlci_id ID of the DLCI to append.
|
||||
*/
|
||||
static void dlci_id_append(uint8_t dlci_id);
|
||||
|
||||
/** Get file handle based on DLCI ID.
|
||||
*
|
||||
* @param dlci_id ID of the DLCI used as the key
|
||||
*
|
||||
* @return Valid object reference or NULL if not found.
|
||||
*/
|
||||
static MuxDataService* file_handle_get(uint8_t dlci_id);
|
||||
|
||||
/** Evaluate is DLCI ID in use.
|
||||
*
|
||||
* @param dlci_id ID of the DLCI yo evaluate
|
||||
*
|
||||
* @return True if in use, false otherwise.
|
||||
*/
|
||||
static bool is_dlci_in_use(uint8_t dlci_id);
|
||||
|
||||
/** Evaluate is DLCI ID queue full.
|
||||
*
|
||||
* @return True if full, false otherwise.
|
||||
*/
|
||||
static bool is_dlci_q_full();
|
||||
|
||||
/** Begin pending self iniated multiplexer open sequence. */
|
||||
static void pending_self_iniated_mux_open_start();
|
||||
|
||||
/** Begin pending self iniated DLCI establishment sequence. */
|
||||
static void pending_self_iniated_dlci_open_start();
|
||||
|
||||
/** Begin pending peer iniated DLCI establishment sequence.
|
||||
*
|
||||
* @param dlci_id ID of the DLCI to establish.
|
||||
*/
|
||||
static void pending_peer_iniated_dlci_open_start(uint8_t dlci_id);
|
||||
|
||||
/** Enqueue user data for transmission.
|
||||
*
|
||||
* @note: This is API is only meant to be used for the multiplexer (user) data service tx. Supplied buffer can be
|
||||
* reused/freed upon call return.
|
||||
*
|
||||
* @param dlci_id ID of the DLCI to use.
|
||||
* @param buffer Begin of the user data.
|
||||
* @param size The number of bytes to write.
|
||||
* @return The number of bytes written, negative error on failure.
|
||||
*/
|
||||
static ssize_t user_data_tx(uint8_t dlci_id, const void* buffer, size_t size);
|
||||
|
||||
/** Read user data into a buffer.
|
||||
*
|
||||
* @note: This is API is only meant to be used for the multiplexer (user) data service rx.
|
||||
*
|
||||
* @param buffer The buffer to read in to.
|
||||
* @param size The number of bytes to read.
|
||||
* @return The number of bytes read, -EAGAIN if no data availabe for read.
|
||||
*/
|
||||
static ssize_t user_data_rx(void* buffer, size_t size);
|
||||
|
||||
/** Clear TX callback pending bit.
|
||||
*
|
||||
* @param bit Bit to clear.
|
||||
*/
|
||||
static void tx_callback_pending_bit_clear(uint8_t bit);
|
||||
|
||||
/** Set TX callback pending bit for supplied DLCI ID.
|
||||
*
|
||||
* @param dlci_id DLCI ID for bit to set.
|
||||
*/
|
||||
static void tx_callback_pending_bit_set(uint8_t dlci_id);
|
||||
|
||||
/** Advance the current TX callback index bit.
|
||||
*
|
||||
* @return The current TX callback index bit after advanced.
|
||||
*/
|
||||
static uint8_t tx_callback_index_advance();
|
||||
|
||||
/** Get the TX callback pending bitmask.
|
||||
*
|
||||
* @return TX callback pending bitmask.
|
||||
*/
|
||||
static uint8_t tx_callback_pending_mask_get();
|
||||
|
||||
/** Dispatch TX callback based on supplied bit.
|
||||
*
|
||||
* @param bit Bit indetifier of callback to dispatch.
|
||||
*/
|
||||
static void tx_callback_dispatch(uint8_t bit);
|
||||
|
||||
/** Run main processing loop for resolving pending TX callbacks and dispatching them if they exists.
|
||||
*/
|
||||
static void tx_callbacks_run();
|
||||
|
||||
/** Get data service object based on supplied bit id.
|
||||
*
|
||||
* @param bit Bit indetifier of data service object to get.
|
||||
* @return Data service object reference.
|
||||
*/
|
||||
static MuxDataService& tx_callback_lookup(uint8_t bit);
|
||||
|
||||
/** Get minimum of 2 supplied paramaters.
|
||||
*
|
||||
* @param size_1 1st param for comparisation.
|
||||
* @param size_2 2nd param for comparisation.
|
||||
* @return Minimum of supplied paramaters.
|
||||
*/
|
||||
static size_t min(uint8_t size_1, size_t size_2);
|
||||
|
||||
/** Enqueue callback to event queue.
|
||||
*/
|
||||
static void event_queue_enqueue();
|
||||
|
||||
/** Verify is FCS valid in RX frame.
|
||||
*
|
||||
* @return True upon valid FCS, false otherwise.
|
||||
*/
|
||||
static bool is_rx_fcs_valid();
|
||||
|
||||
/* Deny object creation. */
|
||||
Mux();
|
||||
|
||||
/* Deny copy constructor. */
|
||||
Mux(const Mux& obj);
|
||||
|
||||
/* Deny assignment operator. */
|
||||
Mux& operator=(const Mux& obj);
|
||||
|
||||
/* Definition for Tx context type. */
|
||||
struct tx_context_t {
|
||||
int timer_id; /* Timer id. */
|
||||
union {
|
||||
uint32_t align_4_byte; /* Force 4-byte alignment. */
|
||||
uint8_t buffer[MBED_CONF_MUX_BUFFER_SIZE]; /* Rx buffer. */
|
||||
};
|
||||
uint8_t retransmit_counter; /* Frame retransmission counter. */
|
||||
uint8_t bytes_remaining; /* Bytes remaining in the buffer to write. */
|
||||
uint8_t offset; /* Offset in the buffer where to write from. */
|
||||
uint8_t tx_callback_context; /* Context for the TX callback dispatching logic as follows:
|
||||
- 4 LO bits contain the pending callback mask
|
||||
- 4 HI bits contain the current bit used for masking */
|
||||
TxState tx_state; /* Tx state machine current state. */
|
||||
|
||||
};
|
||||
|
||||
/* Definition for Rx context type. */
|
||||
struct rx_context_t {
|
||||
union {
|
||||
uint32_t align_4_byte; /* Force 4-byte alignment. */
|
||||
uint8_t buffer[MBED_CONF_MUX_BUFFER_SIZE]; /* Rx buffer. */
|
||||
};
|
||||
uint8_t offset; /* Offset in the buffer where to read to. */
|
||||
uint8_t read_length; /* Amount to read in number of bytes. */
|
||||
RxState rx_state; /* Rx state machine current state. */
|
||||
};
|
||||
|
||||
/* Definition for state type. */
|
||||
struct state_t {
|
||||
uint16_t is_mux_open : 1; /* True when multiplexer is open. */
|
||||
uint16_t is_mux_open_pending : 1; /* True when multiplexer open is pending. */
|
||||
uint16_t is_mux_open_running : 1; /* True when multiplexer open is running. */
|
||||
uint16_t is_dlci_open_pending : 1; /* True when DLCI open is pending. */
|
||||
uint16_t is_dlci_open_running : 1; /* True when DLCI open is running. */
|
||||
uint16_t is_system_thread_context : 1; /* True when current context is system thread context. */
|
||||
uint16_t is_tx_callback_context : 1; /* True when current context is TX callback context. */
|
||||
uint16_t is_user_tx_pending : 1; /* True when user TX is pending. */
|
||||
uint16_t is_user_rx_ready : 1; /* True when user RX is ready/available. */
|
||||
};
|
||||
|
||||
static FileHandle* _serial; /* Serial used. */
|
||||
static events::EventQueue* _event_q; /* Event queue used. */
|
||||
static rtos::Semaphore _semaphore; /* Semaphore used. */
|
||||
static PlatformMutex _mutex; /* Mutex used. */
|
||||
static MuxDataService _mux_objects[MBED_CONF_MUX_DLCI_COUNT]; /* Number of supported DLCIs. */
|
||||
static tx_context_t _tx_context; /* Tx context. */
|
||||
static rx_context_t _rx_context; /* Rx context. */
|
||||
static state_t _state; /* General state context. */
|
||||
static const uint8_t _crctable[MUX_CRC_TABLE_LEN]; /* CRC table used for frame FCS. */
|
||||
static uint8_t _shared_memory; /* Shared memory used passing data between user and
|
||||
system threads. */
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
||||
#endif
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (c) , 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 "mbed_mux.h"
|
||||
|
||||
namespace mbed
|
||||
{
|
||||
|
||||
ssize_t MuxDataService::write(const void* buffer, size_t size)
|
||||
{
|
||||
return Mux::user_data_tx(_dlci, buffer, size);
|
||||
}
|
||||
|
||||
|
||||
ssize_t MuxDataService::read(void *buffer, size_t size)
|
||||
{
|
||||
return Mux::user_data_rx(buffer, size);
|
||||
}
|
||||
|
||||
|
||||
off_t MuxDataService::seek(off_t offset, int whence)
|
||||
{
|
||||
MBED_ASSERT(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int MuxDataService::close()
|
||||
{
|
||||
MBED_ASSERT(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void MuxDataService::sigio(Callback<void()> func)
|
||||
{
|
||||
_sigio_cb = func;
|
||||
}
|
||||
|
||||
} // namespace mbed
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "QUECTEL_BC95_CellularNetwork.h"
|
||||
#include "QUECTEL_BC95_CellularPower.h"
|
||||
|
||||
#include "QUECTEL_BC95.h"
|
||||
|
||||
#define CONNECT_DELIM "\r\n"
|
||||
#define CONNECT_BUFFER_SIZE (1280 + 80 + 80) // AT response + sscanf format
|
||||
#define CONNECT_TIMEOUT 8000
|
||||
|
||||
#define MAX_STARTUP_TRIALS 5
|
||||
#define MAX_RESET_TRIALS 5
|
||||
|
||||
using namespace events;
|
||||
using namespace mbed;
|
||||
|
||||
QUECTEL_BC95::QUECTEL_BC95(EventQueue &queue) : AT_CellularDevice(queue)
|
||||
{
|
||||
}
|
||||
|
||||
QUECTEL_BC95::~QUECTEL_BC95()
|
||||
{
|
||||
}
|
||||
|
||||
CellularNetwork *QUECTEL_BC95::open_network(FileHandle *fh)
|
||||
{
|
||||
if (!_network) {
|
||||
_network = new QUECTEL_BC95_CellularNetwork(*get_at_handler(fh));
|
||||
}
|
||||
return _network;
|
||||
}
|
||||
|
||||
CellularPower *QUECTEL_BC95::open_power(FileHandle *fh)
|
||||
{
|
||||
if (!_power) {
|
||||
_power = new QUECTEL_BC95_CellularPower(*get_at_handler(fh));
|
||||
}
|
||||
return _power;
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef QUECTEL_BC95_H_
|
||||
#define QUECTEL_BC95_H_
|
||||
|
||||
#include "AT_CellularDevice.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
class QUECTEL_BC95 : public AT_CellularDevice
|
||||
{
|
||||
public:
|
||||
|
||||
QUECTEL_BC95(events::EventQueue &queue);
|
||||
virtual ~QUECTEL_BC95();
|
||||
|
||||
public: // CellularDevice
|
||||
virtual CellularNetwork *open_network(FileHandle *fh);
|
||||
virtual CellularPower *open_power(FileHandle *fh);
|
||||
|
||||
public: // NetworkInterface
|
||||
void handle_urc(FileHandle *fh);
|
||||
};
|
||||
} // namespace mbed
|
||||
#endif // QUECTEL_BC95_H_
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "QUECTEL_BC95_CellularNetwork.h"
|
||||
#include "QUECTEL_BC95_CellularStack.h"
|
||||
|
||||
using namespace mbed;
|
||||
|
||||
QUECTEL_BC95_CellularNetwork::QUECTEL_BC95_CellularNetwork(ATHandler &atHandler) : AT_CellularNetwork(atHandler)
|
||||
{
|
||||
//TODO Set default to NB1 or leave it UNKNOWN
|
||||
//_ops_act = operator_t::OPS_NB1;
|
||||
}
|
||||
|
||||
QUECTEL_BC95_CellularNetwork::~QUECTEL_BC95_CellularNetwork()
|
||||
{
|
||||
}
|
||||
|
||||
NetworkStack *QUECTEL_BC95_CellularNetwork::get_stack()
|
||||
{
|
||||
if (!_stack) {
|
||||
_stack = new QUECTEL_BC95_CellularStack(_at, _cid, _ip_stack_type);
|
||||
}
|
||||
return _stack;
|
||||
}
|
||||
|
||||
bool QUECTEL_BC95_CellularNetwork::get_modem_stack_type(nsapi_ip_stack_t requested_stack)
|
||||
{
|
||||
return requested_stack == IPV4_STACK ? true : false;
|
||||
}
|
||||
|
||||
bool QUECTEL_BC95_CellularNetwork::has_registration(RegistrationType reg_tech)
|
||||
{
|
||||
return (reg_tech == C_EREG);
|
||||
}
|
||||
|
||||
nsapi_error_t QUECTEL_BC95_CellularNetwork::set_access_technology_impl(operator_t::RadioAccessTechnology opRat)
|
||||
{
|
||||
if (opRat != operator_t::RAT_NB1) {
|
||||
//TODO: Set as unknown or force to NB1?
|
||||
_op_act = operator_t::RAT_UNKNOWN;
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef QUECTEL_BC95_CELLULAR_NETWORK_H_
|
||||
#define QUECTEL_BC95_CELLULAR_NETWORK_H_
|
||||
|
||||
#include "AT_CellularNetwork.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
class QUECTEL_BC95_CellularNetwork : public AT_CellularNetwork
|
||||
{
|
||||
public:
|
||||
QUECTEL_BC95_CellularNetwork(ATHandler &atHandler);
|
||||
virtual ~QUECTEL_BC95_CellularNetwork();
|
||||
|
||||
/** Provide access to the NetworkStack object
|
||||
*
|
||||
* @return The underlying NetworkStack object
|
||||
*/
|
||||
virtual NetworkStack *get_stack();
|
||||
|
||||
/**
|
||||
* Sets radio access technology.
|
||||
*
|
||||
* @param opRat Radio access technology
|
||||
*
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t set_access_technology_impl(operator_t::RadioAccessTechnology opRat);
|
||||
|
||||
protected:
|
||||
virtual bool get_modem_stack_type(nsapi_ip_stack_t requested_stack);
|
||||
|
||||
/**
|
||||
* Check if modem supports given registration type.
|
||||
*
|
||||
* @param reg_type enum RegistrationType
|
||||
* @return true if given registration type is supported by modem
|
||||
*/
|
||||
virtual bool has_registration(RegistrationType reg_type);
|
||||
};
|
||||
} // namespace mbed
|
||||
#endif // QUECTEL_BC95_CELLULAR_NETWORK_H_
|
|
@ -0,0 +1,50 @@
|
|||
/* 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 <QUECTEL_BC95_CellularPower.h>
|
||||
|
||||
#include "onboard_modem_api.h"
|
||||
using namespace mbed;
|
||||
|
||||
QUECTEL_BC95_CellularPower::QUECTEL_BC95_CellularPower(ATHandler &atHandler) : AT_CellularPower(atHandler)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QUECTEL_BC95_CellularPower::~QUECTEL_BC95_CellularPower()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
nsapi_error_t QUECTEL_BC95_CellularPower::set_at_mode()
|
||||
{
|
||||
_at.lock();
|
||||
_at.flush();
|
||||
_at.cmd_start("AT+CMEE="); // verbose responses
|
||||
_at.write_int(1);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
return _at.unlock_return_error();
|
||||
}
|
||||
|
||||
nsapi_error_t QUECTEL_BC95_CellularPower::reset()
|
||||
{
|
||||
_at.lock();
|
||||
_at.cmd_start("AT+NRB"); // reset to full power levels
|
||||
_at.cmd_stop();
|
||||
_at.resp_start("REBOOTING", true);
|
||||
return _at.unlock_return_error();
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/* 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 TELIT_HE910_CELLULAR_POWER_H_
|
||||
#define TELIT_HE910_CELLULAR_POWER_H_
|
||||
|
||||
#include "AT_CellularPower.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
class QUECTEL_BC95_CellularPower : public AT_CellularPower
|
||||
{
|
||||
public:
|
||||
QUECTEL_BC95_CellularPower(ATHandler &atHandler);
|
||||
virtual ~QUECTEL_BC95_CellularPower();
|
||||
|
||||
public: //from CellularPower
|
||||
/**
|
||||
* Set AT command mode.
|
||||
* @remark must be called after power on to prepare correct AT mode
|
||||
* @return blocking until success or failure
|
||||
*/
|
||||
virtual nsapi_error_t set_at_mode();
|
||||
|
||||
/**
|
||||
* Reset and wake-up cellular device.
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t reset();
|
||||
};
|
||||
} // namespace mbed
|
||||
#endif // TELIT_HE910_CELLULAR_POWER_H_
|
|
@ -0,0 +1,200 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "QUECTEL_BC95_CellularStack.h"
|
||||
#include "CellularUtil.h"
|
||||
|
||||
using namespace mbed;
|
||||
using namespace mbed_cellular_util;
|
||||
|
||||
QUECTEL_BC95_CellularStack::QUECTEL_BC95_CellularStack(ATHandler &atHandler, int cid, nsapi_ip_stack_t stack_type) : AT_CellularStack(atHandler, cid, stack_type)
|
||||
{
|
||||
_at.set_urc_handler("+NSONMI:", mbed::Callback<void()>(this, &QUECTEL_BC95_CellularStack::urc_nsonmi));
|
||||
}
|
||||
|
||||
QUECTEL_BC95_CellularStack::~QUECTEL_BC95_CellularStack()
|
||||
{
|
||||
}
|
||||
|
||||
nsapi_error_t QUECTEL_BC95_CellularStack::socket_listen(nsapi_socket_t handle, int backlog)
|
||||
{
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
nsapi_error_t QUECTEL_BC95_CellularStack::socket_accept(void *server, void **socket, SocketAddress *addr)
|
||||
{
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
void QUECTEL_BC95_CellularStack::urc_nsonmi()
|
||||
{
|
||||
int sock_id =_at.read_int();
|
||||
|
||||
for (int i = 0; i < get_max_socket_count(); i++) {
|
||||
CellularSocket *sock = _socket[i];
|
||||
if (sock && sock->id == sock_id) {
|
||||
if (sock->_cb) {
|
||||
sock->_cb(sock->_data);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int QUECTEL_BC95_CellularStack::get_max_socket_count()
|
||||
{
|
||||
return BC95_SOCKET_MAX;
|
||||
}
|
||||
|
||||
int QUECTEL_BC95_CellularStack::get_max_packet_size()
|
||||
{
|
||||
return BC95_MAX_PACKET_SIZE;
|
||||
}
|
||||
|
||||
bool QUECTEL_BC95_CellularStack::is_protocol_supported(nsapi_protocol_t protocol)
|
||||
{
|
||||
return (protocol == NSAPI_UDP);
|
||||
}
|
||||
|
||||
nsapi_error_t QUECTEL_BC95_CellularStack::socket_close_impl(int sock_id)
|
||||
{
|
||||
_at.cmd_start("AT+NSOCL=");
|
||||
_at.write_int(sock_id);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
|
||||
return _at.get_last_error();
|
||||
}
|
||||
|
||||
nsapi_error_t QUECTEL_BC95_CellularStack::create_socket_impl(CellularSocket *socket)
|
||||
{
|
||||
int sock_id;
|
||||
bool socketOpenWorking = false;
|
||||
|
||||
if (socket->proto == NSAPI_UDP) {
|
||||
|
||||
_at.cmd_start("AT+NSOCR=DGRAM,17,");
|
||||
_at.write_int(socket->localAddress.get_port());
|
||||
_at.write_int(1);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
sock_id = _at.read_int();
|
||||
_at.resp_stop();
|
||||
|
||||
bool socketOpenWorking = (_at.get_last_error() == NSAPI_ERROR_OK);
|
||||
|
||||
if (!socketOpenWorking) {
|
||||
_at.cmd_start("AT+NSOCL=0");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
|
||||
_at.cmd_start("AT+NSOCR=DGRAM,17,");
|
||||
_at.write_int(socket->localAddress.get_port());
|
||||
_at.write_int(1);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
sock_id = _at.read_int();
|
||||
_at.resp_stop();
|
||||
|
||||
socketOpenWorking = (_at.get_last_error() == NSAPI_ERROR_OK);
|
||||
}
|
||||
}
|
||||
|
||||
if (!socketOpenWorking) {
|
||||
return NSAPI_ERROR_NO_SOCKET;
|
||||
}
|
||||
|
||||
// Check for duplicate socket id delivered by modem
|
||||
for (int i = 0; i < BC95_SOCKET_MAX; i++) {
|
||||
CellularSocket *sock = _socket[i];
|
||||
if (sock && sock->created && sock->id == sock_id) {
|
||||
return NSAPI_ERROR_NO_SOCKET;
|
||||
}
|
||||
}
|
||||
|
||||
socket->id = sock_id;
|
||||
socket->created = true;
|
||||
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
nsapi_size_or_error_t QUECTEL_BC95_CellularStack::socket_sendto_impl(CellularSocket *socket, const SocketAddress &address,
|
||||
const void *data, nsapi_size_t size)
|
||||
{
|
||||
int sent_len = 0;
|
||||
|
||||
char hexstr[BC95_MAX_PACKET_SIZE*2 + 1] = {0};
|
||||
char_str_to_hex_str((const char*)data, size, hexstr);
|
||||
|
||||
_at.cmd_start("AT+NSOST=");
|
||||
_at.write_int(socket->id);
|
||||
_at.write_string(address.get_ip_address(), false);
|
||||
_at.write_int(address.get_port());
|
||||
_at.write_int(size);
|
||||
_at.write_string(hexstr, false);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
socket->id = _at.read_int();
|
||||
sent_len = _at.read_int();
|
||||
_at.resp_stop();
|
||||
|
||||
if (_at.get_last_error() == NSAPI_ERROR_OK) {
|
||||
return sent_len;
|
||||
}
|
||||
|
||||
return _at.get_last_error();
|
||||
}
|
||||
|
||||
nsapi_size_or_error_t QUECTEL_BC95_CellularStack::socket_recvfrom_impl(CellularSocket *socket, SocketAddress *address,
|
||||
void *buffer, nsapi_size_t size)
|
||||
{
|
||||
nsapi_size_or_error_t recv_len=0;
|
||||
int port;
|
||||
char ip_address[NSAPI_IP_SIZE];
|
||||
char hexstr[BC95_MAX_PACKET_SIZE*2 + 1] = {0};
|
||||
|
||||
_at.cmd_start("AT+NSORF=");
|
||||
_at.write_int(socket->id);
|
||||
_at.write_int(size);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
// receiving socket id
|
||||
_at.skip_param();
|
||||
_at.read_string(ip_address, sizeof(ip_address));
|
||||
port = _at.read_int();
|
||||
recv_len = _at.read_int();
|
||||
_at.read_string(hexstr, sizeof(hexstr));
|
||||
// remaining length
|
||||
_at.skip_param();
|
||||
|
||||
if (!recv_len || (_at.get_last_error() != NSAPI_ERROR_OK)) {
|
||||
return NSAPI_ERROR_WOULD_BLOCK;
|
||||
}
|
||||
|
||||
if (address) {
|
||||
address->set_ip_address(ip_address);
|
||||
address->set_port(port);
|
||||
}
|
||||
|
||||
if (recv_len > 0) {
|
||||
hex_str_to_char_str((const char*) hexstr, recv_len*2, (char*)buffer);
|
||||
}
|
||||
|
||||
return recv_len;
|
||||
}
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef QUECTEL_BC95_CELLULARSTACK_H_
|
||||
#define QUECTEL_BC95_CELLULARSTACK_H_
|
||||
|
||||
#include "AT_CellularStack.h"
|
||||
|
||||
#define BC95_SOCKET_MAX 7
|
||||
#define BC95_MAX_PACKET_SIZE 512
|
||||
|
||||
namespace mbed {
|
||||
|
||||
class QUECTEL_BC95_CellularStack : public AT_CellularStack
|
||||
{
|
||||
public:
|
||||
QUECTEL_BC95_CellularStack(ATHandler &atHandler, int cid, nsapi_ip_stack_t stack_type);
|
||||
virtual ~QUECTEL_BC95_CellularStack();
|
||||
|
||||
public: // NetworkStack
|
||||
|
||||
/** Listen for connections on a TCP socket
|
||||
*
|
||||
* Marks the socket as a passive socket that can be used to accept
|
||||
* incoming connections.
|
||||
*
|
||||
* @param handle Socket handle
|
||||
* @param backlog Number of pending connections that can be queued
|
||||
* simultaneously
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
virtual nsapi_error_t socket_listen(nsapi_socket_t handle, int backlog);
|
||||
|
||||
/** Accepts a connection on a TCP socket
|
||||
*
|
||||
* The server socket must be bound and set to listen for connections.
|
||||
* On a new connection, creates a network socket and stores it in the
|
||||
* specified handle. The handle must be passed to following calls on
|
||||
* the socket.
|
||||
*
|
||||
* A stack may have a finite number of sockets, in this case
|
||||
* NSAPI_ERROR_NO_SOCKET is returned if no socket is available.
|
||||
*
|
||||
* This call is non-blocking. If accept would block,
|
||||
* NSAPI_ERROR_WOULD_BLOCK is returned immediately.
|
||||
*
|
||||
* @param server Socket handle to server to accept from
|
||||
* @param handle Destination for a handle to the newly created socket
|
||||
* @param address Destination for the remote address or NULL
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
virtual nsapi_error_t socket_accept(nsapi_socket_t server,
|
||||
nsapi_socket_t *handle, SocketAddress *address=0);
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Gets maximum number of sockets modem supports
|
||||
*/
|
||||
virtual int get_max_socket_count();
|
||||
|
||||
/**
|
||||
* Gets maximum packet size
|
||||
*/
|
||||
virtual int get_max_packet_size();
|
||||
|
||||
/**
|
||||
* Checks if modem supports given protocol
|
||||
*
|
||||
* @param protocol Protocol type
|
||||
*/
|
||||
virtual bool is_protocol_supported(nsapi_protocol_t protocol);
|
||||
|
||||
/**
|
||||
* Implements modem specific AT command set for socket closing
|
||||
*
|
||||
* @param sock_id Socket id
|
||||
*/
|
||||
virtual nsapi_error_t socket_close_impl(int sock_id);
|
||||
|
||||
/**
|
||||
* Implements modem specific AT command set for creating socket
|
||||
*
|
||||
* @param socket Cellular socket handle
|
||||
*/
|
||||
virtual nsapi_error_t create_socket_impl(CellularSocket *socket);
|
||||
|
||||
/**
|
||||
* Implements modem specific AT command set for sending data
|
||||
*
|
||||
* @param socket Cellular socket handle
|
||||
* @param address The SocketAddress of the remote host
|
||||
* @param data Buffer of data to send to the host
|
||||
* @param size Size of the buffer in bytes
|
||||
* @return Number of sent bytes on success, negative error
|
||||
* code on failure
|
||||
*/
|
||||
virtual nsapi_size_or_error_t socket_sendto_impl(CellularSocket *socket, const SocketAddress &address,
|
||||
const void *data, nsapi_size_t size);
|
||||
|
||||
/**
|
||||
* Implements modem specific AT command set for receiving data
|
||||
*
|
||||
* @param handle Socket handle
|
||||
* @param address Destination for the source address or NULL
|
||||
* @param buffer Destination buffer for data received from the host
|
||||
* @param size Size of the buffer in bytes
|
||||
* @return Number of received bytes on success, negative error
|
||||
* code on failure
|
||||
*/
|
||||
virtual nsapi_size_or_error_t socket_recvfrom_impl(CellularSocket *socket, SocketAddress *address,
|
||||
void *buffer, nsapi_size_t size);
|
||||
|
||||
private:
|
||||
// URC handlers
|
||||
void urc_nsonmi();
|
||||
};
|
||||
} // namespace mbed
|
||||
#endif /* QUECTEL_BC95_CELLULARSTACK_H_ */
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <QUECTEL/BG96/QUECTEL_BG96.h>
|
||||
#include <QUECTEL/BG96/QUECTEL_BG96_CellularNetwork.h>
|
||||
#include <QUECTEL/BG96/QUECTEL_BG96_CellularStack.h>
|
||||
|
||||
using namespace mbed;
|
||||
using namespace events;
|
||||
|
||||
#define CONNECT_DELIM "\r\n"
|
||||
#define CONNECT_BUFFER_SIZE (1280 + 80 + 80) // AT response + sscanf format
|
||||
#define CONNECT_TIMEOUT 8000
|
||||
|
||||
#define MAX_STARTUP_TRIALS 5
|
||||
#define MAX_RESET_TRIALS 5
|
||||
|
||||
QUECTEL_BG96::QUECTEL_BG96(EventQueue &queue) : AT_CellularDevice(queue)
|
||||
{
|
||||
}
|
||||
|
||||
QUECTEL_BG96::~QUECTEL_BG96()
|
||||
{
|
||||
}
|
||||
|
||||
CellularNetwork *QUECTEL_BG96::open_network(FileHandle *fh)
|
||||
{
|
||||
if (!_network) {
|
||||
_network = new QUECTEL_BG96_CellularNetwork(*get_at_handler(fh));
|
||||
}
|
||||
return _network;
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef QUECTEL_BG96_H_
|
||||
#define QUECTEL_BG96_H_
|
||||
|
||||
#include "AT_CellularDevice.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
#ifdef TARGET_MCU_K64F
|
||||
#define CELLULAR_SERIAL_TX PTC17
|
||||
#define CELLULAR_SERIAL_RX PTC16
|
||||
#else
|
||||
#define CELLULAR_SERIAL_TX PC_1
|
||||
#define CELLULAR_SERIAL_RX PC_0
|
||||
#endif
|
||||
|
||||
class QUECTEL_BG96 : public AT_CellularDevice
|
||||
{
|
||||
public:
|
||||
|
||||
QUECTEL_BG96(events::EventQueue &queue);
|
||||
virtual ~QUECTEL_BG96();
|
||||
|
||||
public: // CellularDevice
|
||||
virtual CellularNetwork *open_network(FileHandle *fh);
|
||||
|
||||
public: // NetworkInterface
|
||||
void handle_urc(FileHandle *fh);
|
||||
};
|
||||
} // namespace mbed
|
||||
#endif // QUECTEL_BG96_H_
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <QUECTEL/BG96/QUECTEL_BG96_CellularNetwork.h>
|
||||
#include <QUECTEL/BG96/QUECTEL_BG96_CellularStack.h>
|
||||
|
||||
using namespace mbed;
|
||||
|
||||
QUECTEL_BG96_CellularNetwork::QUECTEL_BG96_CellularNetwork(ATHandler &atHandler) : AT_CellularNetwork(atHandler)
|
||||
{
|
||||
}
|
||||
|
||||
QUECTEL_BG96_CellularNetwork::~QUECTEL_BG96_CellularNetwork()
|
||||
{
|
||||
}
|
||||
|
||||
bool QUECTEL_BG96_CellularNetwork::get_modem_stack_type(nsapi_ip_stack_t requested_stack)
|
||||
{
|
||||
if ((requested_stack == IPV4_STACK) ||
|
||||
(requested_stack == IPV6_STACK) ||
|
||||
(requested_stack == IPV4V6_STACK)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
NetworkStack *QUECTEL_BG96_CellularNetwork::get_stack()
|
||||
{
|
||||
if (!_stack) {
|
||||
_stack = new QUECTEL_BG96_CellularStack(_at, _cid, _ip_stack_type);
|
||||
}
|
||||
return _stack;
|
||||
}
|
||||
|
||||
nsapi_error_t QUECTEL_BG96_CellularNetwork::set_access_technology_impl(operator_t::RadioAccessTechnology opsAct)
|
||||
{
|
||||
_at.lock();
|
||||
|
||||
switch (opsAct) {
|
||||
case operator_t::RAT_CATM1:
|
||||
_at.cmd_start("AT+QCFG=\"nwscanseq\",020301");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
_at.cmd_start("AT+QCFG=\"nwscanmode\",3,1");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
_at.cmd_start("AT+QCFG=\"iotopmode\",0,1");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
break;
|
||||
case operator_t::RAT_NB1:
|
||||
_at.cmd_start("AT+QCFG=\"nwscanseq\",030201");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
_at.cmd_start("AT+QCFG=\"nwscanmode\",3,1");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
_at.cmd_start("AT+QCFG=\"iotopmode\",1,1");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
break;
|
||||
case operator_t::RAT_GSM:
|
||||
case operator_t::RAT_GSM_COMPACT:
|
||||
case operator_t::RAT_UTRAN:
|
||||
case operator_t::RAT_EGPRS:
|
||||
_at.cmd_start("AT+QCFG=\"nwscanseq\",010203");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
_at.cmd_start("AT+QCFG=\"nwscanmode\",1,1");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
break;
|
||||
default:
|
||||
_at.cmd_start("AT+QCFG=\"nwscanseq\",020301");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
_at.cmd_start("AT+QCFG=\"nwscanmode\",0,1"); //auto mode
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
_at.cmd_start("AT+QCFG=\"iotopmode\",2,1"); //auto mode
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
_at.unlock();
|
||||
_op_act = operator_t::RAT_UNKNOWN;
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return _at.unlock_return_error();
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef QUECTEL_BG96_CELLULAR_NETWORK_H_
|
||||
#define QUECTEL_BG96_CELLULAR_NETWORK_H_
|
||||
|
||||
#include "AT_CellularNetwork.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
class QUECTEL_BG96_CellularNetwork : public AT_CellularNetwork
|
||||
{
|
||||
public:
|
||||
QUECTEL_BG96_CellularNetwork(ATHandler &atHandler);
|
||||
virtual ~QUECTEL_BG96_CellularNetwork();
|
||||
|
||||
/** Provide access to the NetworkStack object
|
||||
*
|
||||
* @return The underlying NetworkStack object
|
||||
*/
|
||||
virtual NetworkStack *get_stack();
|
||||
|
||||
/**
|
||||
* Sets radio access technology.
|
||||
*
|
||||
* @param opRat Access technology
|
||||
*
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t set_access_technology_impl(operator_t::RadioAccessTechnology opRat);
|
||||
|
||||
protected:
|
||||
virtual bool get_modem_stack_type(nsapi_ip_stack_t requested_stack);
|
||||
};
|
||||
} // namespace mbed
|
||||
#endif // QUECTEL_BG96_CELLULAR_NETWORK_H_
|
|
@ -0,0 +1,262 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <QUECTEL/BG96/QUECTEL_BG96_CellularStack.h>
|
||||
#include "CellularLog.h"
|
||||
|
||||
using namespace mbed;
|
||||
|
||||
QUECTEL_BG96_CellularStack::QUECTEL_BG96_CellularStack(ATHandler &atHandler, int cid, nsapi_ip_stack_t stack_type) : AT_CellularStack(atHandler, cid, stack_type)
|
||||
{
|
||||
_at.set_urc_handler("+QIURC: ", mbed::Callback<void()>(this, &QUECTEL_BG96_CellularStack::urc_qiurc));
|
||||
}
|
||||
|
||||
QUECTEL_BG96_CellularStack::~QUECTEL_BG96_CellularStack()
|
||||
{
|
||||
}
|
||||
|
||||
nsapi_error_t QUECTEL_BG96_CellularStack::socket_listen(nsapi_socket_t handle, int backlog)
|
||||
{
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
nsapi_error_t QUECTEL_BG96_CellularStack::socket_accept(void *server, void **socket, SocketAddress *addr)
|
||||
{
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
void QUECTEL_BG96_CellularStack::urc_qiurc()
|
||||
{
|
||||
int sock_id=0;
|
||||
|
||||
_at.lock();
|
||||
(void) _at.skip_param();
|
||||
sock_id = _at.read_int();
|
||||
_at.unlock();
|
||||
|
||||
for (int i = 0; i < get_max_socket_count(); i++) {
|
||||
CellularSocket *sock = _socket[i];
|
||||
if (sock && sock->id == sock_id) {
|
||||
if (sock->_cb) {
|
||||
sock->_cb(sock->_data);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int QUECTEL_BG96_CellularStack::get_max_socket_count()
|
||||
{
|
||||
return BG96_SOCKET_MAX;
|
||||
}
|
||||
|
||||
int QUECTEL_BG96_CellularStack::get_max_packet_size()
|
||||
{
|
||||
return BG96_MAX_PACKET_SIZE;
|
||||
}
|
||||
|
||||
bool QUECTEL_BG96_CellularStack::is_protocol_supported(nsapi_protocol_t protocol)
|
||||
{
|
||||
return (protocol == NSAPI_UDP);
|
||||
}
|
||||
|
||||
nsapi_error_t QUECTEL_BG96_CellularStack::socket_close_impl(int sock_id)
|
||||
{
|
||||
_at.cmd_start("AT+QICLOSE=");
|
||||
_at.write_int(sock_id);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
|
||||
return _at.get_last_error();
|
||||
}
|
||||
|
||||
void QUECTEL_BG96_CellularStack::handle_open_socket_response(int &modem_connect_id, int &err)
|
||||
{
|
||||
// OK
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
// QIOPEN -> should be handled as URC?
|
||||
_at.set_at_timeout(BG96_CREATE_SOCKET_TIMEOUT);
|
||||
_at.resp_start("+QIOPEN:");
|
||||
_at.restore_at_timeout();
|
||||
modem_connect_id = _at.read_int();
|
||||
err = _at.read_int();
|
||||
}
|
||||
nsapi_error_t QUECTEL_BG96_CellularStack::create_socket_impl(CellularSocket *socket)
|
||||
{
|
||||
int modem_connect_id;
|
||||
int request_connect_id = socket->id;
|
||||
int remote_port = 0;
|
||||
int err = -1;
|
||||
|
||||
if (socket->proto == NSAPI_UDP && !socket->connected) {
|
||||
_at.cmd_start("AT+QIOPEN=");
|
||||
_at.write_int(_cid);
|
||||
_at.write_int(request_connect_id);
|
||||
_at.write_string("UDP SERVICE");
|
||||
_at.write_string("127.0.0.1");
|
||||
_at.write_int(remote_port);
|
||||
_at.write_int(socket->localAddress.get_port());
|
||||
_at.write_int(0);
|
||||
_at.cmd_stop();
|
||||
|
||||
handle_open_socket_response(modem_connect_id, err);
|
||||
|
||||
if ((_at.get_last_error() == NSAPI_ERROR_OK) && err) {
|
||||
_at.cmd_start("AT+QICLOSE=");
|
||||
_at.write_int(modem_connect_id);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
|
||||
_at.cmd_start("AT+QIOPEN=");
|
||||
_at.write_int(_cid);
|
||||
_at.write_int(request_connect_id);
|
||||
_at.write_string("UDP SERVICE");
|
||||
_at.write_string("127.0.0.1");
|
||||
_at.write_int(remote_port);
|
||||
_at.write_int(socket->localAddress.get_port());
|
||||
_at.write_int(0);
|
||||
_at.cmd_stop();
|
||||
|
||||
handle_open_socket_response(modem_connect_id, err);
|
||||
}
|
||||
} else if (socket->proto == NSAPI_UDP && socket->connected) {
|
||||
_at.cmd_start("AT+QIOPEN=");
|
||||
_at.write_int(_cid);
|
||||
_at.write_int(request_connect_id);
|
||||
_at.write_string("UDP");
|
||||
_at.write_string(socket->remoteAddress.get_ip_address());
|
||||
_at.write_int(socket->remoteAddress.get_port());
|
||||
_at.cmd_stop();
|
||||
|
||||
handle_open_socket_response(modem_connect_id, err);
|
||||
|
||||
if ((_at.get_last_error() == NSAPI_ERROR_OK) && err) {
|
||||
_at.cmd_start("AT+QICLOSE=");
|
||||
_at.write_int(modem_connect_id);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
|
||||
_at.cmd_start("AT+QIOPEN=");
|
||||
_at.write_int(_cid);
|
||||
_at.write_int(request_connect_id);
|
||||
_at.write_string("UDP");
|
||||
_at.write_string(socket->remoteAddress.get_ip_address());
|
||||
_at.write_int(socket->remoteAddress.get_port());
|
||||
_at.cmd_stop();
|
||||
|
||||
handle_open_socket_response(modem_connect_id, err);
|
||||
}
|
||||
}
|
||||
|
||||
// If opened successfully BUT not requested one, close it
|
||||
if (!err && (modem_connect_id != request_connect_id)) {
|
||||
_at.cmd_start("AT+QICLOSE=");
|
||||
_at.write_int(modem_connect_id);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
}
|
||||
|
||||
nsapi_error_t ret_val = _at.get_last_error();
|
||||
|
||||
socket->created = ((ret_val == NSAPI_ERROR_OK) && (modem_connect_id == request_connect_id));
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
nsapi_size_or_error_t QUECTEL_BG96_CellularStack::socket_sendto_impl(CellularSocket *socket, const SocketAddress &address,
|
||||
const void *data, nsapi_size_t size)
|
||||
{
|
||||
int sent_len = 0;
|
||||
int sent_len_before = 0;
|
||||
int sent_len_after = 0;
|
||||
|
||||
// Get the sent count before sending
|
||||
_at.cmd_start("AT+QISEND=");
|
||||
_at.write_int(socket->id);
|
||||
_at.write_int(0);
|
||||
_at.cmd_stop();
|
||||
|
||||
_at.resp_start("+QISEND:");
|
||||
sent_len_before = _at.read_int();
|
||||
_at.resp_stop();
|
||||
|
||||
// Send
|
||||
_at.cmd_start("AT+QISEND=");
|
||||
_at.write_int(socket->id);
|
||||
_at.write_int(size);
|
||||
_at.write_string(address.get_ip_address());
|
||||
_at.write_int(address.get_port());
|
||||
_at.cmd_stop();
|
||||
|
||||
_at.resp_start(">");
|
||||
_at.write_bytes((uint8_t*)data, size);
|
||||
_at.resp_start();
|
||||
_at.set_stop_tag("\r\n");
|
||||
_at.resp_stop();
|
||||
|
||||
// Get the sent count after sending
|
||||
_at.cmd_start("AT+QISEND=");
|
||||
_at.write_int(socket->id);
|
||||
_at.write_int(0);
|
||||
_at.cmd_stop();
|
||||
|
||||
_at.resp_start("+QISEND:");
|
||||
sent_len_after = _at.read_int();
|
||||
_at.resp_stop();
|
||||
|
||||
if (_at.get_last_error() == NSAPI_ERROR_OK) {
|
||||
sent_len = sent_len_after - sent_len_before;
|
||||
return sent_len;
|
||||
}
|
||||
|
||||
return _at.get_last_error();
|
||||
}
|
||||
|
||||
nsapi_size_or_error_t QUECTEL_BG96_CellularStack::socket_recvfrom_impl(CellularSocket *socket, SocketAddress *address,
|
||||
void *buffer, nsapi_size_t size)
|
||||
{
|
||||
nsapi_size_or_error_t recv_len=0;
|
||||
int port;
|
||||
char ip_address[NSAPI_IP_SIZE + 1];
|
||||
|
||||
_at.cmd_start("AT+QIRD=");
|
||||
_at.write_int(socket->id);
|
||||
_at.cmd_stop();
|
||||
|
||||
_at.resp_start("+QIRD:");
|
||||
recv_len = _at.read_int();
|
||||
_at.read_string(ip_address, sizeof(ip_address));
|
||||
port = _at.read_int();
|
||||
_at.read_bytes((uint8_t*)buffer, recv_len);
|
||||
_at.resp_stop();
|
||||
|
||||
if (!recv_len || (_at.get_last_error() != NSAPI_ERROR_OK)) {
|
||||
return NSAPI_ERROR_WOULD_BLOCK;
|
||||
}
|
||||
|
||||
if (address) {
|
||||
address->set_ip_address(ip_address);
|
||||
address->set_port(port);
|
||||
}
|
||||
|
||||
return recv_len;
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef QUECTEL_BG96_CELLULARSTACK_H_
|
||||
#define QUECTEL_BG96_CELLULARSTACK_H_
|
||||
|
||||
#include "AT_CellularStack.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
#define BG96_SOCKET_MAX 12
|
||||
#define BG96_MAX_PACKET_SIZE 1460
|
||||
#define BG96_CREATE_SOCKET_TIMEOUT 150000 //150 seconds
|
||||
|
||||
class QUECTEL_BG96_CellularStack : public AT_CellularStack
|
||||
{
|
||||
public:
|
||||
QUECTEL_BG96_CellularStack(ATHandler &atHandler, int cid, nsapi_ip_stack_t stack_type);
|
||||
virtual ~QUECTEL_BG96_CellularStack();
|
||||
|
||||
public: // NetworkStack
|
||||
|
||||
/** Listen for connections on a TCP socket
|
||||
*
|
||||
* Marks the socket as a passive socket that can be used to accept
|
||||
* incoming connections.
|
||||
*
|
||||
* @param handle Socket handle
|
||||
* @param backlog Number of pending connections that can be queued
|
||||
* simultaneously
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
virtual nsapi_error_t socket_listen(nsapi_socket_t handle, int backlog);
|
||||
|
||||
/** Accepts a connection on a TCP socket
|
||||
*
|
||||
* The server socket must be bound and set to listen for connections.
|
||||
* On a new connection, creates a network socket and stores it in the
|
||||
* specified handle. The handle must be passed to following calls on
|
||||
* the socket.
|
||||
*
|
||||
* A stack may have a finite number of sockets, in this case
|
||||
* NSAPI_ERROR_NO_SOCKET is returned if no socket is available.
|
||||
*
|
||||
* This call is non-blocking. If accept would block,
|
||||
* NSAPI_ERROR_WOULD_BLOCK is returned immediately.
|
||||
*
|
||||
* @param server Socket handle to server to accept from
|
||||
* @param handle Destination for a handle to the newly created socket
|
||||
* @param address Destination for the remote address or NULL
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
virtual nsapi_error_t socket_accept(nsapi_socket_t server,
|
||||
nsapi_socket_t *handle, SocketAddress *address=0);
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Gets maximum number of sockets modem supports
|
||||
*/
|
||||
virtual int get_max_socket_count();
|
||||
|
||||
/**
|
||||
* Gets maximum packet size
|
||||
*/
|
||||
virtual int get_max_packet_size();
|
||||
|
||||
/**
|
||||
* Checks if modem supports given protocol
|
||||
*
|
||||
* @param protocol Protocol type
|
||||
*/
|
||||
virtual bool is_protocol_supported(nsapi_protocol_t protocol);
|
||||
|
||||
/**
|
||||
* Implements modem specific AT command set for socket closing
|
||||
*
|
||||
* @param sock_id Socket id
|
||||
*/
|
||||
virtual nsapi_error_t socket_close_impl(int sock_id);
|
||||
|
||||
/**
|
||||
* Implements modem specific AT command set for creating socket
|
||||
*
|
||||
* @param socket Cellular socket handle
|
||||
*/
|
||||
virtual nsapi_error_t create_socket_impl(CellularSocket *socket);
|
||||
|
||||
/**
|
||||
* Implements modem specific AT command set for sending data
|
||||
*
|
||||
* @param socket Cellular socket handle
|
||||
* @param address The SocketAddress of the remote host
|
||||
* @param data Buffer of data to send to the host
|
||||
* @param size Size of the buffer in bytes
|
||||
* @return Number of sent bytes on success, negative error
|
||||
* code on failure
|
||||
*/
|
||||
virtual nsapi_size_or_error_t socket_sendto_impl(CellularSocket *socket, const SocketAddress &address,
|
||||
const void *data, nsapi_size_t size);
|
||||
|
||||
/**
|
||||
* Implements modem specific AT command set for receiving data
|
||||
*
|
||||
* @param handle Socket handle
|
||||
* @param address Destination for the source address or NULL
|
||||
* @param buffer Destination buffer for data received from the host
|
||||
* @param size Size of the buffer in bytes
|
||||
* @return Number of received bytes on success, negative error
|
||||
* code on failure
|
||||
*/
|
||||
virtual nsapi_size_or_error_t socket_recvfrom_impl(CellularSocket *socket, SocketAddress *address,
|
||||
void *buffer, nsapi_size_t size);
|
||||
|
||||
private:
|
||||
// URC handlers
|
||||
void urc_qiurc();
|
||||
|
||||
void handle_open_socket_response(int &modem_connect_id, int &err);
|
||||
};
|
||||
} // namespace mbed
|
||||
#endif /* QUECTEL_BG96_CELLULARSTACK_H_ */
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "TELIT_HE910.h"
|
||||
#include "TELIT_HE910_CellularPower.h"
|
||||
#include "TELIT_HE910_CellularNetwork.h"
|
||||
#include "TELIT_HE910_CellularMultiplexer.h"
|
||||
|
||||
using namespace mbed;
|
||||
using namespace events;
|
||||
|
||||
TELIT_HE910::TELIT_HE910(EventQueue &queue) : AT_CellularDevice(queue)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
TELIT_HE910::~TELIT_HE910()
|
||||
{
|
||||
}
|
||||
|
||||
CellularPower *TELIT_HE910::open_power(FileHandle *fh)
|
||||
{
|
||||
if (!_power) {
|
||||
ATHandler *atHandler = get_at_handler(fh);
|
||||
if (atHandler) {
|
||||
_power = new TELIT_HE910_CellularPower(*atHandler);
|
||||
if (!_power) {
|
||||
release_at_handler(atHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
return _power;
|
||||
}
|
||||
|
||||
CellularNetwork *TELIT_HE910::open_network(FileHandle *fh)
|
||||
{
|
||||
if (!_network) {
|
||||
ATHandler *atHandler = get_at_handler(fh);
|
||||
if (atHandler) {
|
||||
_network = new TELIT_HE910_CellularNetwork(*atHandler);
|
||||
if (!_network) {
|
||||
release_at_handler(atHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
return _network;
|
||||
}
|
||||
|
||||
CellularMultiplexer *TELIT_HE910::open_multiplexer(FileHandle *fh)
|
||||
{
|
||||
if (!_multiplexer) {
|
||||
ATHandler *atHandler = get_at_handler(fh);
|
||||
if (atHandler) {
|
||||
_multiplexer = new AT_CellularMultiplexer(*atHandler);
|
||||
if (!_multiplexer) {
|
||||
release_at_handler(atHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _multiplexer;
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2017, 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 CELLULAR_TARGETS_TELIT_HE910_TELIT_HE910_H_
|
||||
#define CELLULAR_TARGETS_TELIT_HE910_TELIT_HE910_H_
|
||||
|
||||
#include "AT_CellularDevice.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
class TELIT_HE910 : public AT_CellularDevice
|
||||
{
|
||||
|
||||
public:
|
||||
TELIT_HE910(events::EventQueue &queue);
|
||||
virtual ~TELIT_HE910();
|
||||
|
||||
public: // from CellularDevice
|
||||
virtual CellularPower *open_power(FileHandle *fh);
|
||||
virtual CellularNetwork *open_network(FileHandle *fh);
|
||||
virtual CellularMultiplexer *open_multiplexer(FileHandle *fh);
|
||||
};
|
||||
} // namespace mbed
|
||||
#endif /* CELLULAR_TARGETS_TELIT_HE910_TELIT_HE910_H_ */
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "TELIT_HE910_CellularMultiplexer.h"
|
||||
|
||||
using namespace mbed;
|
||||
|
||||
TELIT_HE910_CellularMultiplexer::TELIT_HE910_CellularMultiplexer(ATHandler &atHandler)
|
||||
: AT_CellularMultiplexer(atHandler)
|
||||
{
|
||||
}
|
||||
|
||||
TELIT_HE910_CellularMultiplexer::~TELIT_HE910_CellularMultiplexer()
|
||||
{
|
||||
}
|
||||
|
||||
nsapi_error_t TELIT_HE910_CellularMultiplexer::multiplexer_mode_start()
|
||||
{
|
||||
_at.lock();
|
||||
|
||||
_at.cmd_start("AT#SELINT=2");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
|
||||
_at.cmd_start("ATE0V1&K3&D2");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
|
||||
_at.cmd_start("AT+IPR=115200");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
|
||||
_at.cmd_start("AT&W0&P0");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
|
||||
_at.cmd_start("AT#CMUXMODE=5");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
|
||||
_at.cmd_start("AT+CMUX=0");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
|
||||
return _at.unlock_return_error();
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef TELIT_HE910_CELLULARMULTIPLEXER_H_
|
||||
#define TELIT_HE910_CELLULARMULTIPLEXER_H_
|
||||
|
||||
#include "AT_CellularMultiplexer.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
class TELIT_HE910_CellularMultiplexer : public AT_CellularMultiplexer {
|
||||
public:
|
||||
TELIT_HE910_CellularMultiplexer(ATHandler &atHandler);
|
||||
virtual ~TELIT_HE910_CellularMultiplexer();
|
||||
|
||||
// override from AT_CellularMultiplexer
|
||||
virtual nsapi_error_t multiplexer_mode_start();
|
||||
};
|
||||
} // namespace mbed
|
||||
#endif /* TELIT_HE910_CELLULARMULTIPLEXER_H_ */
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <TELIT_HE910_CellularNetwork.h>
|
||||
|
||||
using namespace mbed;
|
||||
|
||||
TELIT_HE910_CellularNetwork::TELIT_HE910_CellularNetwork(ATHandler &atHandler) : AT_CellularNetwork(atHandler)
|
||||
{
|
||||
}
|
||||
|
||||
TELIT_HE910_CellularNetwork::~TELIT_HE910_CellularNetwork()
|
||||
{
|
||||
}
|
||||
|
||||
bool TELIT_HE910_CellularNetwork::get_modem_stack_type(nsapi_ip_stack_t requested_stack)
|
||||
{
|
||||
return requested_stack == IPV4_STACK ? true : false;
|
||||
}
|
||||
|
||||
bool TELIT_HE910_CellularNetwork::has_registration(RegistrationType reg_type)
|
||||
{
|
||||
return (reg_type == C_REG || reg_type == C_GREG);
|
||||
}
|
||||
|
||||
nsapi_error_t TELIT_HE910_CellularNetwork::set_access_technology_impl(operator_t::RadioAccessTechnology opRat)
|
||||
{
|
||||
_op_act = operator_t::RAT_UNKNOWN;
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef TELIT_HE910_CELLULAR_NETWORK_H_
|
||||
#define TELIT_HE910_CELLULAR_NETWORK_H_
|
||||
|
||||
#include "AT_CellularNetwork.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
class TELIT_HE910_CellularNetwork : public AT_CellularNetwork
|
||||
{
|
||||
public:
|
||||
TELIT_HE910_CellularNetwork(ATHandler &atHandler);
|
||||
virtual ~TELIT_HE910_CellularNetwork();
|
||||
|
||||
protected:
|
||||
|
||||
virtual bool get_modem_stack_type(nsapi_ip_stack_t requested_stack);
|
||||
|
||||
/**
|
||||
* Check if modem supports given registration type.
|
||||
*
|
||||
* @param rat enum RegistrationType
|
||||
* @return true if given registration type is supported by modem
|
||||
*/
|
||||
virtual bool has_registration(RegistrationType rat);
|
||||
|
||||
/**
|
||||
* Sets access technology to be scanned.
|
||||
*
|
||||
* @param opRat Access technology
|
||||
*
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t set_access_technology_impl(operator_t::RadioAccessTechnology opRat);
|
||||
};
|
||||
} // namespace mbed
|
||||
#endif // TELIT_HE910_CELLULAR_NETWORK_H_
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "TELIT_HE910_CellularPower.h"
|
||||
// for modem powering up&down
|
||||
#include "onboard_modem_api.h"
|
||||
|
||||
using namespace mbed;
|
||||
|
||||
TELIT_HE910_CellularPower::TELIT_HE910_CellularPower(ATHandler &atHandler) : AT_CellularPower(atHandler)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
TELIT_HE910_CellularPower::~TELIT_HE910_CellularPower()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
nsapi_error_t TELIT_HE910_CellularPower::on()
|
||||
{
|
||||
#if MODEM_ON_BOARD
|
||||
::onboard_modem_init();
|
||||
::onboard_modem_power_up();
|
||||
#endif
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
nsapi_error_t TELIT_HE910_CellularPower::off()
|
||||
{
|
||||
#if MODEM_ON_BOARD
|
||||
::onboard_modem_power_down();
|
||||
#endif
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set AT command mode.
|
||||
* @remark must be called after power on to prepare correct AT mode
|
||||
* @return blocking until success or failure
|
||||
*/
|
||||
nsapi_error_t TELIT_HE910_CellularPower::set_at_mode()
|
||||
{
|
||||
nsapi_error_t err = AT_CellularPower::set_at_mode();
|
||||
if (err != NSAPI_ERROR_OK) {
|
||||
return err;
|
||||
}
|
||||
_at.lock();
|
||||
_at.cmd_start("AT&K0;&C1;&D0");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
|
||||
return _at.unlock_return_error();
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef TELIT_HE910_CELLULAR_POWER_H_
|
||||
#define TELIT_HE910_CELLULAR_POWER_H_
|
||||
|
||||
#include "AT_CellularPower.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
class TELIT_HE910_CellularPower : public AT_CellularPower
|
||||
{
|
||||
public:
|
||||
TELIT_HE910_CellularPower(ATHandler &atHandler);
|
||||
virtual ~TELIT_HE910_CellularPower();
|
||||
|
||||
public: //from CellularPower
|
||||
/**
|
||||
* Set cellular device power on.
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t on();
|
||||
|
||||
/**
|
||||
* Set cellular device power off.
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t off();
|
||||
|
||||
/**
|
||||
* Set AT command mode.
|
||||
* @remark must be called after power on to prepare correct AT mode
|
||||
* @return blocking until success or failure
|
||||
*/
|
||||
virtual nsapi_error_t set_at_mode();
|
||||
};
|
||||
} // namespace mbed
|
||||
#endif // TELIT_HE910_CELLULAR_POWER_H_
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 2017, 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_C027_CellularNetwork.h"
|
||||
#include "UBLOX_C027_CellularPower.h"
|
||||
#include "UBLOX_C027.h"
|
||||
|
||||
using namespace mbed;
|
||||
using namespace events;
|
||||
|
||||
UBLOX_C027::UBLOX_C027(EventQueue &queue) : AT_CellularDevice(queue)
|
||||
{
|
||||
}
|
||||
|
||||
UBLOX_C027::~UBLOX_C027()
|
||||
{
|
||||
}
|
||||
|
||||
CellularNetwork *UBLOX_C027::open_network(FileHandle *fh)
|
||||
{
|
||||
if (!_network) {
|
||||
_network = new UBLOX_C027_CellularNetwork(*get_at_handler(fh));
|
||||
}
|
||||
return _network;
|
||||
}
|
||||
|
||||
CellularPower *UBLOX_C027::open_power(FileHandle *fh)
|
||||
{
|
||||
if (!_power) {
|
||||
_power = new UBLOX_C027_CellularPower(*get_at_handler(fh));
|
||||
}
|
||||
return _power;
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (c) 2017, 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_C027_H_
|
||||
#define UBLOX_C027_H_
|
||||
|
||||
#include "AT_CellularDevice.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
class UBLOX_C027 : public AT_CellularDevice
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
UBLOX_C027(events::EventQueue &queue);
|
||||
virtual ~UBLOX_C027();
|
||||
|
||||
public: // CellularDevice
|
||||
virtual CellularNetwork *open_network(FileHandle *fh);
|
||||
virtual CellularPower *open_power(FileHandle *fh);
|
||||
|
||||
public: // NetworkInterface
|
||||
};
|
||||
} // namespace mbed
|
||||
#endif // UBLOX_C027_H_
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2017, 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_C027_CellularNetwork.h"
|
||||
|
||||
using namespace mbed;
|
||||
|
||||
UBLOX_C027_CellularNetwork::UBLOX_C027_CellularNetwork(ATHandler &atHandler) : AT_CellularNetwork(atHandler)
|
||||
{
|
||||
}
|
||||
|
||||
UBLOX_C027_CellularNetwork::~UBLOX_C027_CellularNetwork()
|
||||
{
|
||||
}
|
||||
|
||||
bool UBLOX_C027_CellularNetwork::get_modem_stack_type(nsapi_ip_stack_t requested_stack)
|
||||
{
|
||||
return requested_stack == IPV4_STACK ? true : false;
|
||||
}
|
||||
|
||||
bool UBLOX_C027_CellularNetwork::has_registration(RegistrationType reg_type)
|
||||
{
|
||||
return (reg_type == C_REG || reg_type == C_GREG);
|
||||
}
|
||||
|
||||
nsapi_error_t UBLOX_C027_CellularNetwork::set_access_technology_impl(operator_t::RadioAccessTechnology opRat)
|
||||
{
|
||||
_op_act = operator_t::RAT_UNKNOWN;
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (c) 2017, 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_C027_CELLULAR_NETWORK_H_
|
||||
#define UBLOX_C027_CELLULAR_NETWORK_H_
|
||||
|
||||
#include "AT_CellularNetwork.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
class UBLOX_C027_CellularNetwork : public AT_CellularNetwork
|
||||
{
|
||||
public:
|
||||
UBLOX_C027_CellularNetwork(ATHandler &atHandler);
|
||||
virtual ~UBLOX_C027_CellularNetwork();
|
||||
|
||||
protected:
|
||||
virtual bool get_modem_stack_type(nsapi_ip_stack_t requested_stack);
|
||||
|
||||
/**
|
||||
* Check if modem supports given registration type.
|
||||
*
|
||||
* @param rat enum RegistrationType
|
||||
* @return true if given registration type is supported by modem
|
||||
*/
|
||||
virtual bool has_registration(RegistrationType rat);
|
||||
|
||||
/**
|
||||
* Sets access technology to be scanned.
|
||||
*
|
||||
* @param opRat Access technology
|
||||
*
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t set_access_technology_impl(operator_t::RadioAccessTechnology opRat);
|
||||
};
|
||||
} // namespace mbed
|
||||
#endif // UBLOX_C027_CELLULAR_NETWORK_H_
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (c) 2017, 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 "onboard_modem_api.h"
|
||||
|
||||
#include "UBLOX_C027_CellularPower.h"
|
||||
|
||||
using namespace mbed;
|
||||
|
||||
UBLOX_C027_CellularPower::UBLOX_C027_CellularPower(ATHandler &atHandler) : AT_CellularPower(atHandler)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
UBLOX_C027_CellularPower::~UBLOX_C027_CellularPower()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
nsapi_error_t UBLOX_C027_CellularPower::on()
|
||||
{
|
||||
#if MODEM_ON_BOARD
|
||||
::onboard_modem_init();
|
||||
::onboard_modem_power_up();
|
||||
#endif
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
nsapi_error_t UBLOX_C027_CellularPower::off()
|
||||
{
|
||||
#if MODEM_ON_BOARD
|
||||
::onboard_modem_power_down();
|
||||
#endif
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (c) 2017, 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_C027_CELLULARPOWER_H_
|
||||
#define UBLOX_C027_CELLULARPOWER_H_
|
||||
|
||||
#include "AT_CellularPower.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
class UBLOX_C027_CellularPower : public AT_CellularPower
|
||||
{
|
||||
public:
|
||||
UBLOX_C027_CellularPower(ATHandler &atHandler);
|
||||
virtual ~UBLOX_C027_CellularPower();
|
||||
|
||||
public: //from CellularPower
|
||||
/**
|
||||
* Set cellular device power on.
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t on();
|
||||
|
||||
/**
|
||||
* Set cellular device power off.
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t off();
|
||||
};
|
||||
} // namespace mbed
|
||||
#endif // UBLOX_C027_CELLULARPOWER_H_
|
Loading…
Reference in New Issue