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