mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #6496 from jarvte/async_cellular
standard non-blocking NetworkInterface::connectpull/6620/head
commit
a463b075db
|
@ -12,6 +12,10 @@ This is the Github repo for Mbed cellular connectivity:
|
|||
common Common and utility sources
|
||||
targets Vendor specific cellular module adaptations
|
||||
|
||||
TESTS Cellular Greentea test
|
||||
|
||||
UNITTESTS Cellular unit test
|
||||
|
||||
## Known limitations
|
||||
|
||||
**Please note that this is a first release of Cellular framework and is subject to further development in future.**
|
||||
|
@ -24,7 +28,9 @@ You can find currently supported cellular modules in the `framework/targets/` fo
|
|||
|
||||
## Cellular configuration
|
||||
|
||||
You can change cellular defaults in the `mbed_app.json` configuration file:
|
||||
You can change cellular defaults in the `mbed_lib.json` configuration file.
|
||||
|
||||
You can also override cellular defaults in the `mbed_app.json` configuration file:
|
||||
|
||||
"config": {
|
||||
"cellular_plmn": {
|
||||
|
@ -62,6 +68,14 @@ You can define the debug tracing level in the `mbed_app.json` configuration file
|
|||
}
|
||||
}
|
||||
|
||||
## Greentea tests
|
||||
|
||||
The `TESTS` folder contains Greentea tests for cellular specific classes. You need to give relevant configuration file with `--app-config` parameter, e.g.:
|
||||
|
||||
mbed test -n features-cellular-tests-* --app-config features\cellular\TESTS\socket\udp\template_mbed_app.json -vv
|
||||
|
||||
Note that Greentea tests use SIM PIN so you need to change that or your SIM card may get locked.
|
||||
|
||||
## Unit tests
|
||||
|
||||
The `UNITTESTS` folder contains unit tests for cellular specific classes. Unit tests are based on the stubbing method.
|
||||
|
|
|
@ -1,82 +0,0 @@
|
|||
/*
|
||||
* 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_TESTS_H
|
||||
#define CELLULAR_TESTS_H
|
||||
|
||||
#include "CellularUtil.h" // for CELLULAR_ helper macros
|
||||
#include "CellularTargets.h"
|
||||
|
||||
#ifdef CELLULAR_DEVICE
|
||||
|
||||
#include "mbed_events.h"
|
||||
|
||||
#include "greentea-client/test_env.h"
|
||||
#include "unity.h"
|
||||
#include "utest.h"
|
||||
|
||||
#include "CellularLog.h"
|
||||
|
||||
#include CELLULAR_STRINGIFY(CELLULAR_DEVICE.h)
|
||||
extern EventQueue queue;
|
||||
extern CELLULAR_DEVICE cellularDevice;
|
||||
|
||||
extern UARTSerial serial;
|
||||
extern CellularNetwork *network;
|
||||
|
||||
extern CellularSMS *sms;
|
||||
extern CellularPower *pwr;
|
||||
extern CellularSIM *sim;
|
||||
|
||||
|
||||
/**
|
||||
* TEST CASES DEFINED HERE AND in main.cpp
|
||||
*/
|
||||
|
||||
// power
|
||||
void test_create_power(void);
|
||||
|
||||
// SIM
|
||||
void test_get_sim_state(void);
|
||||
void test_set_pin(void);
|
||||
void test_change_pin(void);
|
||||
|
||||
// sms
|
||||
void test_sms_init(void);
|
||||
|
||||
// network
|
||||
void test_attach(void);
|
||||
void test_connect(void);
|
||||
void test_get_ip_address(void);
|
||||
void test_disconnect(void);
|
||||
|
||||
// stack
|
||||
void test_socket_open(void);
|
||||
void test_socket_bind(void);
|
||||
/*
|
||||
void test_socket_set_blocking();
|
||||
void test_socket_send_receive_blocking();
|
||||
*/
|
||||
void test_socket_set_non_blocking();
|
||||
void test_socket_send_receive_non_blocking();
|
||||
void test_socket_close(void);
|
||||
|
||||
// Test closing all interface via device
|
||||
void test_close_interfaces(void);
|
||||
|
||||
#endif // CELLULAR_DEVICE
|
||||
|
||||
#endif // CELLULAR_TESTS_H
|
|
@ -1,107 +0,0 @@
|
|||
/*
|
||||
* 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 "CellularTests.h"
|
||||
|
||||
#if !defined(MBED_CONF_NSAPI_PRESENT)
|
||||
#error [NOT_SUPPORTED] A json configuration file is needed. Skipping this build.
|
||||
#endif
|
||||
|
||||
#ifndef CELLULAR_DEVICE
|
||||
#error [NOT_SUPPORTED] CELLULAR_DEVICE must be defined for this test
|
||||
#endif
|
||||
|
||||
EventQueue queue(32 * EVENTS_EVENT_SIZE);
|
||||
Thread t;
|
||||
CELLULAR_DEVICE cellularDevice(queue);
|
||||
|
||||
UARTSerial serial(MDMTXD, MDMRXD, MBED_CONF_PLATFORM_DEFAULT_SERIAL_BAUD_RATE);
|
||||
CellularNetwork *network = NULL;
|
||||
CellularPower *pwr = NULL;
|
||||
CellularSIM *sim = NULL;
|
||||
CellularSMS *sms = NULL;
|
||||
|
||||
using namespace utest::v1;
|
||||
|
||||
// using namespace mbed;
|
||||
utest::v1::status_t greentea_failure_handler(const Case *const source, const failure_t reason)
|
||||
{
|
||||
greentea_case_failure_abort_handler(source, reason);
|
||||
return STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
Case cases[] = {
|
||||
// power test
|
||||
Case("Create power", test_create_power, greentea_failure_handler),
|
||||
#ifdef MBED_CONF_APP_CELLULAR_SIM_PIN
|
||||
// sim test
|
||||
Case("test get SIM state", test_get_sim_state, greentea_failure_handler),
|
||||
Case("SIM set pin", test_set_pin, greentea_failure_handler),
|
||||
Case("SIM change pin", test_change_pin, greentea_failure_handler),
|
||||
#endif
|
||||
// network tests
|
||||
Case("attach", test_attach, greentea_failure_handler),
|
||||
// SMS tests
|
||||
Case("SMS init", test_sms_init, greentea_failure_handler),
|
||||
// network tests
|
||||
Case("connect", test_connect, greentea_failure_handler),
|
||||
Case("get_ip_address", test_get_ip_address, greentea_failure_handler),
|
||||
// stack tests
|
||||
Case("open", test_socket_open, greentea_failure_handler),
|
||||
Case("bind", test_socket_bind, greentea_failure_handler),
|
||||
// Case("set socket blocking", test_socket_set_blocking, greentea_failure_handler),
|
||||
// Case("socket send receive in blocking mode", test_socket_send_receive_blocking, greentea_failure_handler),
|
||||
Case("set socket non blocking", test_socket_set_non_blocking, greentea_failure_handler),
|
||||
Case("socket send receive in non blocking mode", test_socket_send_receive_non_blocking, greentea_failure_handler),
|
||||
Case("close", test_socket_close, greentea_failure_handler),
|
||||
// network tests
|
||||
Case("disconnect", test_disconnect, greentea_failure_handler),
|
||||
|
||||
// test closing of all interface, must be the last test case
|
||||
Case("Close all Interfaces", test_close_interfaces, greentea_failure_handler)
|
||||
};
|
||||
|
||||
utest::v1::status_t test_setup(const size_t number_of_cases)
|
||||
{
|
||||
GREENTEA_SETUP(300, "default_auto");
|
||||
|
||||
return verbose_test_setup_handler(number_of_cases);
|
||||
}
|
||||
|
||||
Specification specification(test_setup, cases);
|
||||
|
||||
void test_close_interfaces()
|
||||
{
|
||||
// SMS is already closed in it's test
|
||||
cellularDevice.close_network();
|
||||
cellularDevice.close_sim();
|
||||
cellularDevice.close_power();
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
#if defined (MDMRTS) && defined (MDMCTS)
|
||||
serial.set_flow_control(SerialBase::RTSCTS, MDMRTS, MDMCTS);
|
||||
#endif
|
||||
pwr = cellularDevice.open_power(&serial);
|
||||
sim = cellularDevice.open_sim(&serial);
|
||||
sms = cellularDevice.open_sms(&serial);
|
||||
network = cellularDevice.open_network(&serial);
|
||||
|
||||
t.start(callback(&queue, &EventQueue::dispatch_forever));
|
||||
return Harness::run(specification);
|
||||
}
|
|
@ -1,104 +0,0 @@
|
|||
/*
|
||||
* 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 "CellularTests.h"
|
||||
#ifdef CELLULAR_DEVICE
|
||||
|
||||
using namespace mbed;
|
||||
|
||||
static bool wait_register()
|
||||
{
|
||||
tr_info("Try registering to network...");
|
||||
if (network->set_registration() != NSAPI_ERROR_OK) {
|
||||
tr_error("Network registration request failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
CellularNetwork::RegistrationStatus status;
|
||||
for (int i=0; i<180; i++) {
|
||||
tr_info("Register to network %d...", i);
|
||||
for (int type = 0; type < CellularNetwork::C_MAX; type++) {
|
||||
if (network->get_registration_status((CellularNetwork::RegistrationType)type, status) == NSAPI_ERROR_OK) {
|
||||
tr_info("status %d...", status);
|
||||
switch (status) {
|
||||
case CellularNetwork::RegisteredRoaming:
|
||||
// fall-through
|
||||
case CellularNetwork::RegisteredHomeNetwork:
|
||||
tr_info("Registered to network.");
|
||||
return true;
|
||||
case CellularNetwork::RegisteredSMSOnlyRoaming:
|
||||
// fall-through
|
||||
case CellularNetwork::RegisteredSMSOnlyHome:
|
||||
tr_warn("SMS only network registration!");
|
||||
return true;
|
||||
case CellularNetwork::RegisteredCSFBNotPreferredRoaming:
|
||||
// fall-through
|
||||
case CellularNetwork::RegisteredCSFBNotPreferredHome:
|
||||
tr_warn("Not preferred network registration!");
|
||||
return true;
|
||||
case CellularNetwork::AttachedEmergencyOnly:
|
||||
tr_warn("Emergency only network registration!");
|
||||
return true;
|
||||
case CellularNetwork::RegistrationDenied:
|
||||
tr_warn("Network registration denied!");
|
||||
wait(i);
|
||||
break;
|
||||
case CellularNetwork::NotRegistered:
|
||||
case CellularNetwork::Unknown:
|
||||
case CellularNetwork::SearchingNetwork:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
wait(1);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void test_attach()
|
||||
{
|
||||
cellularDevice.set_timeout(120*1000); // 120 second timeout for at commands after power is up. It might take time to register, attach and connect
|
||||
tr_info("Register to network.");
|
||||
TEST_ASSERT(wait_register());
|
||||
tr_info("Attach to network.");
|
||||
nsapi_error_t err = network->set_attach();
|
||||
TEST_ASSERT(!err);
|
||||
CellularNetwork::AttachStatus status;
|
||||
err = network->get_attach(status);
|
||||
TEST_ASSERT(!err);
|
||||
}
|
||||
|
||||
void test_connect()
|
||||
{
|
||||
nsapi_error_t err = network->connect();
|
||||
TEST_ASSERT(!err);
|
||||
}
|
||||
|
||||
void test_get_ip_address()
|
||||
{
|
||||
const char *ip = network->get_ip_address();
|
||||
TEST_ASSERT(ip && ip[0]);
|
||||
tr_info("IP: %s\r\n", ip);
|
||||
}
|
||||
|
||||
void test_disconnect()
|
||||
{
|
||||
nsapi_error_t err = network->disconnect();
|
||||
TEST_ASSERT(!err);
|
||||
}
|
||||
|
||||
#endif // CELLULAR_DEVICE
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
* 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 "CellularTests.h"
|
||||
|
||||
#ifdef CELLULAR_DEVICE
|
||||
|
||||
using namespace mbed;
|
||||
|
||||
static bool start_cellular_at(CellularPower *pwr)
|
||||
{
|
||||
nsapi_error_t err = pwr->off();
|
||||
if (err != NSAPI_ERROR_OK && err != NSAPI_ERROR_UNSUPPORTED) {
|
||||
return false;
|
||||
}
|
||||
err = pwr->on();
|
||||
if (err != NSAPI_ERROR_OK && err != NSAPI_ERROR_UNSUPPORTED) {
|
||||
return false;
|
||||
}
|
||||
tr_info("Wait for cellular device 180 seconds...");
|
||||
for (int i = 0; i < 180; i++) {
|
||||
if (pwr->set_at_mode() == NSAPI_ERROR_OK) {
|
||||
return true;
|
||||
}
|
||||
wait(1);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void test_create_power()
|
||||
{
|
||||
TEST_ASSERT(start_cellular_at(pwr));
|
||||
|
||||
tr_info("Cellular device is ready!");
|
||||
}
|
||||
|
||||
// TODO: tests still missing for off, sleep, opt_power_save_mode, opt_receive_period
|
||||
|
||||
#endif // CELLULAR_DEVICE
|
|
@ -1,90 +0,0 @@
|
|||
/*
|
||||
* 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 "CellularTests.h"
|
||||
|
||||
#ifdef CELLULAR_DEVICE
|
||||
|
||||
#ifdef MBED_CONF_APP_CELLULAR_SIM_PIN
|
||||
|
||||
using namespace mbed;
|
||||
|
||||
void test_get_sim_state()
|
||||
{
|
||||
wait(1);
|
||||
CellularSIM::SimState state = CellularSIM::SimStateUnknown;
|
||||
tr_info("Wait SIM for 180 seconds...");
|
||||
for (int i = 0; i < 180; i++) {
|
||||
CellularSIM::SimState tmp_state;
|
||||
if ((sim->get_sim_state(tmp_state) == NSAPI_ERROR_OK) && tmp_state != CellularSIM::SimStateUnknown) {
|
||||
state = tmp_state;
|
||||
break;
|
||||
}
|
||||
}
|
||||
TEST_ASSERT_MESSAGE(state == CellularSIM::SimStateReady || state == CellularSIM::SimStatePinNeeded ||
|
||||
state == CellularSIM::SimStatePukNeeded, "Invalid SIM state");
|
||||
}
|
||||
|
||||
// creates PIN which is different than one defined in MBED_CONF_APP_CELLULAR_SIM_PIN
|
||||
static void create_random_pin(char* random_pin)
|
||||
{
|
||||
|
||||
char s[11];
|
||||
do {
|
||||
sprintf(s,"%d", rand());
|
||||
|
||||
} while (strncmp(s, MBED_CONF_APP_CELLULAR_SIM_PIN, 4) == 0);
|
||||
|
||||
strncpy(random_pin, s, 4);
|
||||
random_pin[4] = '\0';
|
||||
}
|
||||
|
||||
void test_set_pin()
|
||||
{
|
||||
// run test only if sim is not in ready state as then sim interface will return NSAPI_ERROR_OK
|
||||
nsapi_error_t err;
|
||||
CellularSIM::SimState state = CellularSIM::SimStateUnknown;
|
||||
if ((sim->get_sim_state(state) == NSAPI_ERROR_OK) && (state != CellularSIM::SimStateReady)) {
|
||||
char random_pin[5];
|
||||
create_random_pin(random_pin);
|
||||
err = sim->set_pin(random_pin);
|
||||
TEST_ASSERT_MESSAGE(err != 0, "Setting random pin should fail");
|
||||
}
|
||||
|
||||
err = sim->set_pin(MBED_CONF_APP_CELLULAR_SIM_PIN);
|
||||
char err_msg[60];
|
||||
sprintf(err_msg, "Setting correct pin: %s failed with: %d", MBED_CONF_APP_CELLULAR_SIM_PIN, err);
|
||||
TEST_ASSERT_MESSAGE(err == 0, err_msg);
|
||||
}
|
||||
|
||||
void test_change_pin()
|
||||
{
|
||||
char random_pin[5];
|
||||
create_random_pin(random_pin);
|
||||
nsapi_error_t err = sim->change_pin(MBED_CONF_APP_CELLULAR_SIM_PIN, random_pin);
|
||||
|
||||
char err_msg[60];
|
||||
sprintf(err_msg, "Change from original pin failed with: %d", err);
|
||||
TEST_ASSERT_MESSAGE(err == NSAPI_ERROR_OK, err_msg);
|
||||
|
||||
err = sim->change_pin(random_pin, MBED_CONF_APP_CELLULAR_SIM_PIN);
|
||||
sprintf(err_msg, "Change back original pin failed with: %d", err);
|
||||
TEST_ASSERT_MESSAGE(err == NSAPI_ERROR_OK, err_msg);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif // CELLULAR_DEVICE
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* 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 "CellularTests.h"
|
||||
|
||||
#ifdef CELLULAR_DEVICE
|
||||
|
||||
using namespace mbed;
|
||||
|
||||
void test_sms_init()
|
||||
{
|
||||
// for some weird reason if we don't wait for few seconds we get SIM Busy error in initialize even is SIM is ready...
|
||||
wait(3);
|
||||
|
||||
// check SIM state as we have tested sim and it might not be ready
|
||||
for (int i = 0; i < MAX_SIM_READY_WAITING_TIME; i++) {
|
||||
CellularSIM::SimState state;
|
||||
if (sim->get_sim_state(state) == NSAPI_ERROR_OK && state == CellularSIM::SimStateReady) {
|
||||
break;
|
||||
}
|
||||
wait(1);
|
||||
}
|
||||
|
||||
nsapi_error_t err = sms->initialize(CellularSMS::CellularSMSMmodeText);
|
||||
char err_msg[60];
|
||||
sprintf(err_msg, "SMS initialize failed with: %d", err);
|
||||
|
||||
cellularDevice.close_sms();
|
||||
sms = NULL;
|
||||
TEST_ASSERT_MESSAGE(!err, err_msg);
|
||||
}
|
||||
|
||||
#endif // CELLULAR_DEVICE
|
|
@ -1,120 +0,0 @@
|
|||
/*
|
||||
* 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 "CellularTests.h"
|
||||
|
||||
#ifdef CELLULAR_DEVICE
|
||||
|
||||
using namespace mbed;
|
||||
|
||||
static UDPSocket socket;
|
||||
#define SERVER_IP_ADDR "52.215.34.155"
|
||||
#define SERVER_UDP_PORT 7
|
||||
static rtos::Semaphore sock_event;
|
||||
|
||||
void test_socket_open()
|
||||
{
|
||||
nsapi_error_t err = socket.open(network);
|
||||
TEST_ASSERT(err == NSAPI_ERROR_OK);
|
||||
}
|
||||
|
||||
void test_socket_bind()
|
||||
{
|
||||
nsapi_error_t err = socket.bind(3030);
|
||||
TEST_ASSERT(!err);
|
||||
}
|
||||
|
||||
/*
|
||||
void test_socket_set_blocking()
|
||||
{
|
||||
//socket.set_blocking(true);
|
||||
socket.set_timeout(5000);
|
||||
}
|
||||
|
||||
void test_socket_send_receive_blocking()
|
||||
{
|
||||
char receive_buffer[CELLULAR_MTU] = {0};
|
||||
char send_buffer[] = { 'H', 'e', 'l', 'l', 'u', 'l', 'a', 'r', '!' };
|
||||
int send_count = 0;
|
||||
int send_tries = 1;
|
||||
int max_send_tries = 3;
|
||||
|
||||
// Send to echo server
|
||||
while (send_tries <= max_send_tries) {
|
||||
tr_info("ONE!!!");
|
||||
send_count = socket.sendto(SERVER_IP_ADDR, SERVER_UDP_PORT, send_buffer, sizeof(send_buffer));
|
||||
TEST_ASSERT_MESSAGE(send_count == sizeof(send_buffer), "Sent count doesnt match sent buffer!");
|
||||
send_tries++;
|
||||
|
||||
// Read response
|
||||
SocketAddress address;
|
||||
int receive_count = 0;
|
||||
// 2 tries. First recv attempt should be blocked and wait for a max 5 seconds for socket read flag
|
||||
int recv_tries = 2;
|
||||
while (recv_tries >= 0) {
|
||||
tr_info("RECV!!!");
|
||||
receive_count = socket.recvfrom(&address, receive_buffer, sizeof(receive_buffer));
|
||||
if (receive_count > 0) {
|
||||
break;
|
||||
}
|
||||
recv_tries--;
|
||||
wait(1);
|
||||
}
|
||||
TEST_ASSERT_MESSAGE(receive_count == send_count, "Receive and Sent count dont match!");
|
||||
TEST_ASSERT_MESSAGE(strncmp(send_buffer, receive_buffer, send_count) == 0, "Sent data doesn't match received data while in ECHO");
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
static void socket_sigio_cb()
|
||||
{
|
||||
sock_event.release();
|
||||
}
|
||||
|
||||
void test_socket_set_non_blocking()
|
||||
{
|
||||
socket.set_blocking(false);
|
||||
socket.sigio(socket_sigio_cb);
|
||||
}
|
||||
|
||||
void test_socket_send_receive_non_blocking()
|
||||
{
|
||||
char receive_buffer[1500] = {0};
|
||||
char send_buffer[] = { 'H', 'e', 'l', 'l', 'u', 'l', 'a', 'r', '!' };
|
||||
|
||||
// Send to echo server
|
||||
int send_count = socket.sendto(SERVER_IP_ADDR, SERVER_UDP_PORT, send_buffer, sizeof(send_buffer));
|
||||
TEST_ASSERT(send_count == sizeof(send_buffer));
|
||||
|
||||
int32_t event;
|
||||
event = sock_event.wait(10000);
|
||||
TEST_ASSERT_MESSAGE( event>=1, "No Socket event within 10 seconds");
|
||||
|
||||
// Read response
|
||||
SocketAddress address;
|
||||
int receive_count = socket.recvfrom(&address, receive_buffer, sizeof(receive_buffer));
|
||||
TEST_ASSERT_MESSAGE(receive_count == send_count, "Receive and Sent count dont match!");
|
||||
TEST_ASSERT_MESSAGE(strncmp(send_buffer, receive_buffer, send_count) == 0, "Sent data doesn't match received data while in ECHO");
|
||||
}
|
||||
|
||||
|
||||
void test_socket_close()
|
||||
{
|
||||
nsapi_error_t err = socket.close();
|
||||
TEST_ASSERT(!err);
|
||||
}
|
||||
|
||||
#endif // CELLULAR_DEVICE
|
|
@ -0,0 +1,203 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if !defined(MBED_CONF_NSAPI_PRESENT)
|
||||
#error [NOT_SUPPORTED] A json configuration file is needed. Skipping this build.
|
||||
#endif
|
||||
|
||||
#include "CellularUtil.h" // for CELLULAR_ helper macros
|
||||
#include "CellularTargets.h"
|
||||
|
||||
#ifndef CELLULAR_DEVICE
|
||||
#error [NOT_SUPPORTED] CELLULAR_DEVICE must be defined
|
||||
#endif
|
||||
|
||||
#ifndef MBED_CONF_APP_CELLULAR_SIM_PIN
|
||||
#error [NOT_SUPPORTED] SIM pin code is needed. Skipping this build.
|
||||
#endif
|
||||
|
||||
#include "greentea-client/test_env.h"
|
||||
#include "unity.h"
|
||||
#include "utest.h"
|
||||
|
||||
#include "mbed.h"
|
||||
|
||||
#include "CellularConnectionFSM.h"
|
||||
|
||||
#if MBED_CONF_CELLULAR_USE_APN_LOOKUP || MBED_CONF_PPP_CELL_IFACE_APN_LOOKUP
|
||||
#include "APN_db.h"
|
||||
#endif //MBED_CONF_CELLULAR_USE_APN_LOOKUP || MBED_CONF_PPP_CELL_IFACE_APN_LOOKUP
|
||||
|
||||
#include "CellularLog.h"
|
||||
|
||||
#define NETWORK_TIMEOUT (180*1000)
|
||||
#define SOCKET_TIMEOUT (30*1000)
|
||||
|
||||
#define ECHO_SERVER_NAME "echo.mbedcloudtesting.com"
|
||||
#define ECHO_SERVER_UDP_PORT 7
|
||||
|
||||
static CellularConnectionFSM::CellularState cellular_target_state;
|
||||
static UARTSerial cellular_serial(MDMTXD, MDMRXD, MBED_CONF_PLATFORM_DEFAULT_SERIAL_BAUD_RATE);
|
||||
static rtos::Semaphore network_semaphore(0);
|
||||
static CellularConnectionFSM cellular;
|
||||
|
||||
static SocketAddress echo_server_addr;
|
||||
|
||||
class EchoSocket : public UDPSocket {
|
||||
public:
|
||||
EchoSocket(int size) : UDPSocket(), _async_flag(0), _data(0), _size(size) {
|
||||
}
|
||||
virtual ~EchoSocket() {
|
||||
delete _data;
|
||||
}
|
||||
void set_async(int async) {
|
||||
_async_flag = async;
|
||||
if (_async_flag) {
|
||||
set_blocking(false);
|
||||
sigio(callback(this, &EchoSocket::async_callback));
|
||||
} else {
|
||||
set_blocking(true);
|
||||
set_timeout(SOCKET_TIMEOUT);
|
||||
sigio(NULL);
|
||||
}
|
||||
|
||||
}
|
||||
void test_sendto(const char *const hostname = NULL) {
|
||||
_data = new uint8_t[_size];
|
||||
for (int i=0; i<_size; i++) {
|
||||
_data[i] = (uint8_t)rand();
|
||||
}
|
||||
// clear pending events
|
||||
while ((EchoSocket::eventFlags.wait_any(_async_flag, SOCKET_TIMEOUT) & (osFlagsError | _async_flag)) == _async_flag);
|
||||
if (hostname) {
|
||||
TEST_ASSERT(sendto(hostname, ECHO_SERVER_UDP_PORT, _data, _size) == _size);
|
||||
} else {
|
||||
TEST_ASSERT(sendto(echo_server_addr, _data, _size) == _size);
|
||||
}
|
||||
}
|
||||
void test_recvfrom() {
|
||||
if (_async_flag) {
|
||||
TEST_ASSERT((EchoSocket::eventFlags.wait_any(_async_flag, SOCKET_TIMEOUT) & (osFlagsError | _async_flag)) == _async_flag);
|
||||
}
|
||||
uint8_t *buf = new uint8_t[_size];
|
||||
memset(buf, 0, _size);
|
||||
SocketAddress recv_address;
|
||||
|
||||
TEST_ASSERT(recvfrom(&recv_address, buf, _size) == _size);
|
||||
|
||||
TEST_ASSERT(recv_address == echo_server_addr);
|
||||
TEST_ASSERT(memcmp(_data, buf, _size) == 0);
|
||||
delete buf;
|
||||
delete _data;
|
||||
_data = 0;
|
||||
}
|
||||
private:
|
||||
void async_callback() {
|
||||
EchoSocket::eventFlags.set(_async_flag);
|
||||
}
|
||||
uint8_t *_data;
|
||||
int _size;
|
||||
uint32_t _async_flag; // 0 for blocking socket, signal bit for async
|
||||
static rtos::EventFlags eventFlags;
|
||||
};
|
||||
|
||||
rtos::EventFlags EchoSocket::eventFlags;
|
||||
|
||||
static void network_callback(nsapi_event_t ev, intptr_t ptr)
|
||||
{
|
||||
if (ev == NSAPI_EVENT_CONNECTION_STATUS_CHANGE) {
|
||||
if (ptr == NSAPI_STATUS_GLOBAL_UP) {
|
||||
MBED_ASSERT(network_semaphore.release() == osOK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void udp_network_stack()
|
||||
{
|
||||
cellular.set_serial(&cellular_serial);
|
||||
TEST_ASSERT(cellular.init() == NSAPI_ERROR_OK);
|
||||
#if defined (MDMRTS) && defined (MDMCTS)
|
||||
cellular_serial.set_flow_control(SerialBase::RTSCTS, MDMRTS, MDMCTS);
|
||||
#endif
|
||||
cellular.attach(&network_callback);
|
||||
TEST_ASSERT(cellular.start_dispatch() == NSAPI_ERROR_OK);
|
||||
cellular.set_sim_pin(MBED_CONF_APP_CELLULAR_SIM_PIN);
|
||||
cellular_target_state = CellularConnectionFSM::STATE_CONNECTED;
|
||||
TEST_ASSERT(cellular.continue_to_state(cellular_target_state) == NSAPI_ERROR_OK);
|
||||
TEST_ASSERT(network_semaphore.wait(NETWORK_TIMEOUT) == 1);
|
||||
}
|
||||
|
||||
static void udp_gethostbyname()
|
||||
{
|
||||
TEST_ASSERT(cellular.get_network()->gethostbyname(ECHO_SERVER_NAME, &echo_server_addr) == 0);
|
||||
tr_info("HOST: %s", echo_server_addr.get_ip_address());
|
||||
echo_server_addr.set_port(7);
|
||||
wait(1);
|
||||
}
|
||||
|
||||
static void udp_socket_send_receive()
|
||||
{
|
||||
EchoSocket echo_socket(4);
|
||||
TEST_ASSERT(echo_socket.open(cellular.get_network()) == NSAPI_ERROR_OK);
|
||||
echo_socket.set_async(0);
|
||||
echo_socket.test_sendto();
|
||||
echo_socket.test_recvfrom();
|
||||
TEST_ASSERT(echo_socket.close() == NSAPI_ERROR_OK);
|
||||
wait(1);
|
||||
}
|
||||
|
||||
static void udp_socket_send_receive_async()
|
||||
{
|
||||
EchoSocket echo_socket(4);
|
||||
TEST_ASSERT(echo_socket.open(cellular.get_network()) == NSAPI_ERROR_OK);
|
||||
echo_socket.set_async(1);
|
||||
echo_socket.test_sendto();
|
||||
echo_socket.test_recvfrom();
|
||||
TEST_ASSERT(echo_socket.close() == NSAPI_ERROR_OK);
|
||||
wait(1);
|
||||
}
|
||||
|
||||
using namespace utest::v1;
|
||||
|
||||
static utest::v1::status_t greentea_failure_handler(const Case *const source, const failure_t reason)
|
||||
{
|
||||
greentea_case_failure_abort_handler(source, reason);
|
||||
return STATUS_ABORT;
|
||||
}
|
||||
|
||||
static Case cases[] = {
|
||||
Case("UDP network stack", udp_network_stack, greentea_failure_handler),
|
||||
Case("UDP gethostbyname", udp_gethostbyname, greentea_failure_handler),
|
||||
Case("UDP socket send/receive", udp_socket_send_receive, greentea_failure_handler),
|
||||
Case("UDP socket send/receive async", udp_socket_send_receive_async, greentea_failure_handler),
|
||||
//Case("UDP socket multiple simultaneous", udp_socket_multiple_simultaneous, greentea_failure_handler),
|
||||
};
|
||||
|
||||
static utest::v1::status_t test_setup(const size_t number_of_cases)
|
||||
{
|
||||
GREENTEA_SETUP(10*60, "default_auto"); // network registration may take up to 180 seconds, DNS query a couple of minutes, etc.
|
||||
return verbose_test_setup_handler(number_of_cases);
|
||||
}
|
||||
|
||||
static Specification specification(test_setup, cases);
|
||||
|
||||
int main()
|
||||
{
|
||||
mbed_trace_init();
|
||||
|
||||
return Harness::run(specification);
|
||||
}
|
|
@ -1,30 +1,39 @@
|
|||
{
|
||||
"config": {
|
||||
"sock-type": "UDP",
|
||||
"network-interface":{
|
||||
"help": "Options are ETHERNET,CELLULAR",
|
||||
"value": "CELLULAR"
|
||||
},
|
||||
"cellular_sim_pin": {
|
||||
"help": "PIN code",
|
||||
"value": "\"1234\""
|
||||
},
|
||||
"apn": {
|
||||
"help": "The APN string to use for this SIM/network, set to 0 if none",
|
||||
"value": 0
|
||||
},
|
||||
"username": {
|
||||
"help": "The user name string to use for this APN, set to zero if none",
|
||||
"value": 0
|
||||
},
|
||||
"password": {
|
||||
"help": "The password string to use for this APN, set to 0 if none",
|
||||
"value": 0
|
||||
},
|
||||
"trace-level": {
|
||||
"help": "Options are TRACE_LEVEL_ERROR,TRACE_LEVEL_WARN,TRACE_LEVEL_INFO,TRACE_LEVEL_DEBUG",
|
||||
"macro_name": "MBED_TRACE_MAX_LEVEL",
|
||||
"value": "TRACE_LEVEL_INFO"
|
||||
}
|
||||
},
|
||||
},
|
||||
"target_overrides": {
|
||||
"*": {
|
||||
"ppp-cell-iface.apn-lookup": false,
|
||||
"cellular.use-apn-lookup": false,
|
||||
"target.features_add": ["LWIP", "COMMON_PAL"],
|
||||
"mbed-trace.enable": true,
|
||||
"mbed-trace.enable": false,
|
||||
"lwip.ipv4-enabled": true,
|
||||
"lwip.ethernet-enabled": false,
|
||||
"lwip.ipv6-enabled": true,
|
||||
"lwip.tcp-enabled": false,
|
||||
"lwip.ppp-enabled": true,
|
||||
"lwip.tcp-enabled": true,
|
||||
"lwip.ethernet-enabled": false,
|
||||
"platform.stdio-convert-newlines": true,
|
||||
"platform.stdio-baud-rate": 115200,
|
||||
"platform.default-serial-baud-rate": 115200
|
||||
}
|
||||
}
|
|
@ -195,8 +195,8 @@ void Test_AT_CellularNetwork::test_AT_CellularNetwork_set_access_technology()
|
|||
ATHandler at(&fh1, que, 0, ",");
|
||||
|
||||
AT_CellularNetwork cn(at);
|
||||
CHECK(NSAPI_ERROR_UNSUPPORTED == cn.set_access_technology(CellularNetwork::operator_t::RAT_UNKNOWN));
|
||||
CHECK(NSAPI_ERROR_UNSUPPORTED == cn.set_access_technology(CellularNetwork::operator_t::RAT_GSM_COMPACT));
|
||||
CHECK(NSAPI_ERROR_UNSUPPORTED == cn.set_access_technology(CellularNetwork::RAT_UNKNOWN));
|
||||
CHECK(NSAPI_ERROR_UNSUPPORTED == cn.set_access_technology(CellularNetwork::RAT_GSM_COMPACT));
|
||||
}
|
||||
|
||||
void Test_AT_CellularNetwork::test_AT_CellularNetwork_scan_plmn()
|
||||
|
|
|
@ -287,7 +287,7 @@ void Test_ATHandler::test_ATHandler_cmd_start()
|
|||
ATHandler at(&fh1, que, 0, ",");
|
||||
mbed_poll_stub::revents_value = POLLOUT;
|
||||
mbed_poll_stub::int_value = 1;
|
||||
fh1.size_value = 1;
|
||||
fh1.size_value = 3;
|
||||
at.cmd_start("s");
|
||||
mbed_poll_stub::revents_value = POLLIN;
|
||||
mbed_poll_stub::int_value = 0;
|
||||
|
@ -303,12 +303,13 @@ void Test_ATHandler::test_ATHandler_write_int()
|
|||
FileHandle_stub fh1;
|
||||
|
||||
ATHandler at(&fh1, que, 0, ",");
|
||||
fh1.size_value = -1;
|
||||
at.write_int(4);
|
||||
|
||||
at.clear_error();
|
||||
mbed_poll_stub::revents_value = POLLOUT;
|
||||
mbed_poll_stub::int_value = 1;
|
||||
fh1.size_value = 1;
|
||||
fh1.size_value = 6;
|
||||
at.write_int(4);
|
||||
|
||||
at.write_int(2147483647);
|
||||
|
@ -331,7 +332,7 @@ void Test_ATHandler::test_ATHandler_write_string()
|
|||
at.clear_error();
|
||||
mbed_poll_stub::revents_value = POLLOUT;
|
||||
mbed_poll_stub::int_value = 1;
|
||||
fh1.size_value = 1;
|
||||
fh1.size_value = -1;
|
||||
at.cmd_start("s");
|
||||
at.write_string("help", true);
|
||||
CHECK(NSAPI_ERROR_DEVICE_ERROR == at.get_last_error());
|
||||
|
@ -339,7 +340,7 @@ void Test_ATHandler::test_ATHandler_write_string()
|
|||
at.clear_error();
|
||||
mbed_poll_stub::revents_value = POLLOUT;
|
||||
mbed_poll_stub::int_value = 1;
|
||||
fh1.size_value = 3;
|
||||
fh1.size_value = -1;
|
||||
at.write_string("help", true);
|
||||
CHECK(NSAPI_ERROR_DEVICE_ERROR == at.get_last_error());
|
||||
|
||||
|
@ -357,6 +358,7 @@ void Test_ATHandler::test_ATHandler_cmd_stop()
|
|||
FileHandle_stub fh1;
|
||||
|
||||
ATHandler at(&fh1, que, 0, ",");
|
||||
fh1.size_value = -1;
|
||||
at.cmd_stop();
|
||||
|
||||
at.write_string("help", true);
|
||||
|
@ -371,6 +373,7 @@ void Test_ATHandler::test_ATHandler_write_bytes()
|
|||
FileHandle_stub fh1;
|
||||
|
||||
ATHandler at(&fh1, que, 0, ",");
|
||||
fh1.size_value = -1;
|
||||
uint8_t data[] = "data";
|
||||
at.write_bytes(data, 4);
|
||||
|
||||
|
|
|
@ -79,9 +79,10 @@ void ATHandler::set_file_handle(FileHandle *fh)
|
|||
{
|
||||
}
|
||||
|
||||
void ATHandler::set_urc_handler(const char *urc, mbed::Callback<void()> cb)
|
||||
nsapi_error_t ATHandler::set_urc_handler(const char *urc, mbed::Callback<void()> cb)
|
||||
{
|
||||
ATHandler_stub::callback = cb;
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
nsapi_error_t ATHandler::get_last_error() const
|
||||
|
|
|
@ -33,6 +33,11 @@ AT_CellularNetwork::~AT_CellularNetwork()
|
|||
{
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::init()
|
||||
{
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::set_credentials(const char *apn,
|
||||
const char *username, const char *password)
|
||||
{
|
||||
|
@ -56,6 +61,11 @@ nsapi_error_t AT_CellularNetwork::connect()
|
|||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::activate_context()
|
||||
{
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::open_data_channel()
|
||||
{
|
||||
return NSAPI_ERROR_OK;
|
||||
|
@ -100,11 +110,17 @@ nsapi_ip_stack_t AT_CellularNetwork::string_to_stack_type(const char* pdp_type)
|
|||
return IPV4_STACK;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::set_registration_urc(bool urc_on)
|
||||
nsapi_error_t AT_CellularNetwork::set_registration_urc(RegistrationType type, bool urc_on)
|
||||
{
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::get_network_registering_mode(NWRegisteringMode& mode)
|
||||
{
|
||||
mode = NWModeAutomatic;
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::set_registration(const char *plmn)
|
||||
{
|
||||
return NSAPI_ERROR_OK;
|
||||
|
@ -171,16 +187,22 @@ void AT_CellularNetwork::urc_no_carrier()
|
|||
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::set_access_technology_impl(operator_t::RadioAccessTechnology opsAct)
|
||||
nsapi_error_t AT_CellularNetwork::set_access_technology_impl(RadioAccessTechnology opsAct)
|
||||
{
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::set_access_technology(operator_t::RadioAccessTechnology opAct)
|
||||
nsapi_error_t AT_CellularNetwork::set_access_technology(RadioAccessTechnology opAct)
|
||||
{
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::get_access_technology(RadioAccessTechnology& rat)
|
||||
{
|
||||
rat = RAT_CATM1;
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::scan_plmn(operList_t &operators, int &opsCount)
|
||||
{
|
||||
return NSAPI_ERROR_OK;
|
||||
|
|
|
@ -64,3 +64,13 @@ nsapi_error_t AT_CellularPower::opt_receive_period(int mode, EDRXAccessTechnolog
|
|||
{
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularPower::set_device_ready_urc_cb(mbed::Callback<void()> callback)
|
||||
{
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
void AT_CellularPower::remove_device_ready_urc_cb(mbed::Callback<void()> callback){
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ static uint8_t filehandle_stub_table_pos = 0;
|
|||
class FileHandle_stub : public FileHandle
|
||||
{
|
||||
public:
|
||||
size_t size_value;
|
||||
ssize_t size_value;
|
||||
|
||||
FileHandle_stub() {size_value = 0;}
|
||||
|
||||
|
@ -47,9 +47,11 @@ public:
|
|||
}
|
||||
|
||||
virtual ssize_t write(const void *buffer, size_t size){
|
||||
if( size_value ) {
|
||||
if (size_value > 0) {
|
||||
size_value--;
|
||||
return size;
|
||||
} else if (size_value < 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -23,11 +23,13 @@
|
|||
#define MBED_TRACE_MAX_LEVEL TRACE_LEVEL_INFO
|
||||
#endif
|
||||
#include "CellularLog.h"
|
||||
#include "CellularCommon.h"
|
||||
|
||||
// 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_CONNECT (60*1000)
|
||||
#define TIMEOUT_REGISTRATION (180*1000)
|
||||
|
||||
// maximum time when retrying network register, attach and connect in seconds ( 20minutes )
|
||||
|
@ -35,42 +37,65 @@
|
|||
|
||||
#define RETRY_COUNT_DEFAULT 3
|
||||
|
||||
namespace mbed {
|
||||
namespace mbed
|
||||
{
|
||||
|
||||
CellularConnectionFSM::CellularConnectionFSM() :
|
||||
_serial(0), _state(STATE_INIT), _next_state(_state), _status_callback(0), _network(0), _power(0), _sim(0),
|
||||
_queue(8 * EVENTS_EVENT_SIZE), _queue_thread(0), _retry_count(0), _state_retry_count(0), _at_queue(8 * EVENTS_EVENT_SIZE)
|
||||
_serial(0), _state(STATE_INIT), _next_state(_state), _status_callback(0), _event_status_cb(0), _network(0), _power(0), _sim(0),
|
||||
_queue(8 * EVENTS_EVENT_SIZE), _queue_thread(0), _cellularDevice(0), _retry_count(0), _event_timeout(-1),
|
||||
_at_queue(8 * EVENTS_EVENT_SIZE), _event_id(0)
|
||||
{
|
||||
memset(_sim_pin, 0, sizeof(_sim_pin));
|
||||
#if MBED_CONF_CELLULAR_RANDOM_MAX_START_DELAY == 0
|
||||
_start_time = 0;
|
||||
#else
|
||||
// so that not every device don't start at the exact same time (for example after power outage)
|
||||
_start_time = rand() % (MBED_CONF_CELLULAR_RANDOM_MAX_START_DELAY);
|
||||
#endif // MBED_CONF_CELLULAR_RANDOM_MAX_START_DELAY
|
||||
|
||||
// set initial retry values in seconds
|
||||
_retry_timeout_array[0] = 1;
|
||||
_retry_timeout_array[0] = 1; // double time on each retry in order to keep network happy
|
||||
_retry_timeout_array[1] = 2;
|
||||
_retry_timeout_array[2] = 4;
|
||||
_retry_timeout_array[3] = 16;
|
||||
_retry_timeout_array[4] = 32;
|
||||
_retry_timeout_array[5] = 60;
|
||||
_retry_timeout_array[6] = 120;
|
||||
_retry_timeout_array[7] = 360;
|
||||
_retry_timeout_array[3] = 8;
|
||||
_retry_timeout_array[4] = 16;
|
||||
_retry_timeout_array[5] = 32;
|
||||
_retry_timeout_array[6] = 64;
|
||||
_retry_timeout_array[7] = 128; // if around two minutes was not enough then let's wait much longer
|
||||
_retry_timeout_array[8] = 600;
|
||||
_retry_timeout_array[9] = TIMEOUT_NETWORK_MAX;
|
||||
_retry_array_length = MAX_RETRY_ARRAY_SIZE;
|
||||
|
||||
_cellularDevice = new CELLULAR_DEVICE(_at_queue);
|
||||
}
|
||||
|
||||
CellularConnectionFSM::~CellularConnectionFSM()
|
||||
{
|
||||
stop();
|
||||
delete _cellularDevice;
|
||||
}
|
||||
|
||||
void CellularConnectionFSM::stop()
|
||||
{
|
||||
tr_info("CellularConnectionUtil::stop");
|
||||
if (_cellularDevice) {
|
||||
_cellularDevice->close_power();
|
||||
_cellularDevice->close_network();
|
||||
}
|
||||
if (_queue_thread) {
|
||||
_queue_thread->terminate();
|
||||
delete _queue_thread;
|
||||
_queue_thread = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
nsapi_error_t CellularConnectionFSM::init()
|
||||
{
|
||||
tr_info("CELLULAR_DEVICE: %s", CELLULAR_STRINGIFY(CELLULAR_DEVICE));
|
||||
_cellularDevice = new CELLULAR_DEVICE(_at_queue);
|
||||
if (!_cellularDevice) {
|
||||
stop();
|
||||
return NSAPI_ERROR_NO_MEMORY;
|
||||
}
|
||||
|
||||
_power = _cellularDevice->open_power(_serial);
|
||||
if (!_power) {
|
||||
stop();
|
||||
|
@ -90,18 +115,15 @@ nsapi_error_t CellularConnectionFSM::init()
|
|||
|
||||
_at_queue.chain(&_queue);
|
||||
|
||||
tr_info("init done...");
|
||||
return NSAPI_ERROR_OK;
|
||||
_retry_count = 0;
|
||||
_state = STATE_INIT;
|
||||
_next_state = STATE_INIT;
|
||||
|
||||
return _network->init();
|
||||
}
|
||||
|
||||
bool CellularConnectionFSM::open_power(FileHandle *fh)
|
||||
bool CellularConnectionFSM::power_on()
|
||||
{
|
||||
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) {
|
||||
tr_warn("Cellular start failed. Power off/on.");
|
||||
|
@ -117,6 +139,7 @@ bool CellularConnectionFSM::open_power(FileHandle *fh)
|
|||
void CellularConnectionFSM::set_sim_pin(const char * sim_pin)
|
||||
{
|
||||
strncpy(_sim_pin, sim_pin, sizeof(_sim_pin));
|
||||
_sim_pin[sizeof(_sim_pin)-1] = '\0';
|
||||
}
|
||||
|
||||
bool CellularConnectionFSM::open_sim()
|
||||
|
@ -124,53 +147,45 @@ bool CellularConnectionFSM::open_sim()
|
|||
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) {
|
||||
tr_info("Waiting for SIM (state %d)...", state);
|
||||
if (_sim->get_sim_state(state) != NSAPI_ERROR_OK) {
|
||||
tr_info("Waiting for SIM (err while reading)...");
|
||||
return false;
|
||||
}
|
||||
tr_info("Initial SIM state: %d", state);
|
||||
|
||||
if (strlen(_sim_pin)) {
|
||||
nsapi_error_t err;
|
||||
if (state == CellularSIM::SimStatePinNeeded) {
|
||||
tr_info("SIM pin required, entering pin: %s", _sim_pin);
|
||||
err = _sim->set_pin(_sim_pin);
|
||||
if (err) {
|
||||
tr_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;
|
||||
switch (state) {
|
||||
case CellularSIM::SimStateReady:
|
||||
tr_info("SIM Ready");
|
||||
break;
|
||||
case CellularSIM::SimStatePinNeeded: {
|
||||
if (strlen(_sim_pin)) {
|
||||
tr_info("SIM pin required, entering pin: %s", _sim_pin);
|
||||
nsapi_error_t err = _sim->set_pin(_sim_pin);
|
||||
if (err) {
|
||||
tr_error("SIM pin set failed with: %d, bailing out...", err);
|
||||
}
|
||||
tr_info("SIM state: %d", state);
|
||||
return false;
|
||||
} else {
|
||||
tr_warn("PIN required but No SIM pin provided.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tr_info("No SIM pin provided.");
|
||||
break;
|
||||
case CellularSIM::SimStatePukNeeded:
|
||||
tr_info("SIM PUK code needed...");
|
||||
break;
|
||||
case CellularSIM::SimStateUnknown:
|
||||
tr_info("SIM, unknown state...");
|
||||
break;
|
||||
default:
|
||||
MBED_ASSERT(1);
|
||||
break;
|
||||
}
|
||||
|
||||
if (_event_status_cb) {
|
||||
_event_status_cb((nsapi_event_t)CellularSIMStatusChanged, state);
|
||||
}
|
||||
|
||||
return state == CellularSIM::SimStateReady;
|
||||
}
|
||||
|
||||
void CellularConnectionFSM::device_ready()
|
||||
{
|
||||
CellularInformation *info = _cellularDevice->open_information(_serial);
|
||||
char device_info_buf[2048]; // may be up to 2048 according to 3GPP
|
||||
|
||||
if (info->get_manufacturer(device_info_buf, sizeof(device_info_buf)) == NSAPI_ERROR_OK) {
|
||||
tr_info("Cellular device manufacturer: %s", device_info_buf);
|
||||
}
|
||||
if (info->get_model(device_info_buf, sizeof(device_info_buf)) == NSAPI_ERROR_OK) {
|
||||
tr_info("Cellular device model: %s", device_info_buf);
|
||||
}
|
||||
if (info->get_revision(device_info_buf, sizeof(device_info_buf)) == NSAPI_ERROR_OK) {
|
||||
tr_info("Cellular device revision: %s", device_info_buf);
|
||||
}
|
||||
}
|
||||
|
||||
bool CellularConnectionFSM::set_network_registration(char *plmn)
|
||||
{
|
||||
if (_network->set_registration(plmn) != NSAPI_ERROR_OK) {
|
||||
|
@ -180,6 +195,23 @@ bool CellularConnectionFSM::set_network_registration(char *plmn)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool CellularConnectionFSM::is_registered()
|
||||
{
|
||||
CellularNetwork::RegistrationStatus status;
|
||||
bool is_registered = false;
|
||||
|
||||
for (int type = 0; type < CellularNetwork::C_MAX; type++) {
|
||||
if (get_network_registration((CellularNetwork::RegistrationType) type, status, is_registered)) {
|
||||
tr_debug("get_network_registration: type=%d, status=%d", type, status);
|
||||
if (is_registered) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return is_registered;
|
||||
}
|
||||
|
||||
bool CellularConnectionFSM::get_network_registration(CellularNetwork::RegistrationType type,
|
||||
CellularNetwork::RegistrationStatus &status, bool &is_registered)
|
||||
{
|
||||
|
@ -195,19 +227,19 @@ bool CellularConnectionFSM::get_network_registration(CellularNetwork::Registrati
|
|||
switch (status) {
|
||||
case CellularNetwork::RegisteredRoaming:
|
||||
is_roaming = true;
|
||||
// fall-through
|
||||
// fall-through
|
||||
case CellularNetwork::RegisteredHomeNetwork:
|
||||
is_registered = true;
|
||||
break;
|
||||
case CellularNetwork::RegisteredSMSOnlyRoaming:
|
||||
is_roaming = true;
|
||||
// fall-through
|
||||
// fall-through
|
||||
case CellularNetwork::RegisteredSMSOnlyHome:
|
||||
tr_warn("SMS only network registration!");
|
||||
break;
|
||||
case CellularNetwork::RegisteredCSFBNotPreferredRoaming:
|
||||
is_roaming = true;
|
||||
// fall-through
|
||||
// fall-through
|
||||
case CellularNetwork::RegisteredCSFBNotPreferredHome:
|
||||
tr_warn("Not preferred network registration!");
|
||||
break;
|
||||
|
@ -255,10 +287,46 @@ void CellularConnectionFSM::report_failure(const char* msg)
|
|||
}
|
||||
}
|
||||
|
||||
const char* CellularConnectionFSM::get_state_string(CellularState state)
|
||||
{
|
||||
static const char *strings[] = { "Init", "Power", "Device ready", "SIM pin", "Registering network", "Attaching network", "Connecting network", "Connected"};
|
||||
return strings[state];
|
||||
}
|
||||
|
||||
nsapi_error_t CellularConnectionFSM::is_automatic_registering(bool& auto_reg)
|
||||
{
|
||||
CellularNetwork::NWRegisteringMode mode;
|
||||
nsapi_error_t err = _network->get_network_registering_mode(mode);
|
||||
if (err == NSAPI_ERROR_OK) {
|
||||
tr_debug("automatic registering mode: %d", mode);
|
||||
auto_reg = (mode == CellularNetwork::NWModeAutomatic);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
nsapi_error_t CellularConnectionFSM::continue_from_state(CellularState state)
|
||||
{
|
||||
tr_info("Continue state from %s to %s", get_state_string((CellularConnectionFSM::CellularState)_state),
|
||||
get_state_string((CellularConnectionFSM::CellularState)state));
|
||||
_state = state;
|
||||
_next_state = state;
|
||||
_retry_count = 0;
|
||||
if (!_queue.call_in(0, callback(this, &CellularConnectionFSM::event))) {
|
||||
stop();
|
||||
return NSAPI_ERROR_NO_MEMORY;
|
||||
}
|
||||
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
nsapi_error_t CellularConnectionFSM::continue_to_state(CellularState state)
|
||||
{
|
||||
_retry_count = 0;
|
||||
if (state < _state) {
|
||||
_state = state;
|
||||
} else {
|
||||
// update next state so that we don't continue from previous state
|
||||
_state = _next_state;
|
||||
}
|
||||
if (!_queue.call_in(0, callback(this, &CellularConnectionFSM::event))) {
|
||||
stop();
|
||||
|
@ -268,223 +336,200 @@ nsapi_error_t CellularConnectionFSM::continue_to_state(CellularState state)
|
|||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
void CellularConnectionFSM::enter_to_state(CellularState state)
|
||||
{
|
||||
_next_state = state;
|
||||
_retry_count = 0;
|
||||
}
|
||||
|
||||
void CellularConnectionFSM::retry_state_or_fail()
|
||||
{
|
||||
if (++_retry_count < MAX_RETRY_ARRAY_SIZE) {
|
||||
tr_debug("Retry State %s, retry %d/%d", get_state_string(_state), _retry_count, MAX_RETRY_ARRAY_SIZE);
|
||||
_event_timeout = _retry_timeout_array[_retry_count];
|
||||
} else {
|
||||
report_failure(get_state_string(_state));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void CellularConnectionFSM::state_init()
|
||||
{
|
||||
_event_timeout = _start_time;
|
||||
tr_info("Init state, waiting %d ms before POWER state)", _start_time);
|
||||
enter_to_state(STATE_POWER_ON);
|
||||
}
|
||||
|
||||
void CellularConnectionFSM::state_power_on()
|
||||
{
|
||||
_cellularDevice->set_timeout(TIMEOUT_POWER_ON);
|
||||
tr_info("Cellular power ON (timeout %d ms)", TIMEOUT_POWER_ON);
|
||||
if (power_on()) {
|
||||
enter_to_state(STATE_DEVICE_READY);
|
||||
} else {
|
||||
// retry to power on device
|
||||
retry_state_or_fail();
|
||||
}
|
||||
}
|
||||
|
||||
bool CellularConnectionFSM::device_ready()
|
||||
{
|
||||
tr_info("Cellular device ready");
|
||||
if (_event_status_cb) {
|
||||
_event_status_cb((nsapi_event_t)CellularDeviceReady, 0);
|
||||
}
|
||||
|
||||
_power->remove_device_ready_urc_cb(mbed::callback(this, &CellularConnectionFSM::ready_urc_cb));
|
||||
|
||||
bool success = false;
|
||||
for (int type = 0; type < CellularNetwork::C_MAX; type++) {
|
||||
if (!_network->set_registration_urc((CellularNetwork::RegistrationType)type, true)) {
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
if (!success) {
|
||||
tr_error("Failed to set any URC's for registration");
|
||||
report_failure(get_state_string(_state));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CellularConnectionFSM::state_device_ready()
|
||||
{
|
||||
_cellularDevice->set_timeout(TIMEOUT_POWER_ON);
|
||||
if (_power->set_at_mode() == NSAPI_ERROR_OK) {
|
||||
if (device_ready()) {
|
||||
enter_to_state(STATE_SIM_PIN);
|
||||
}
|
||||
} else {
|
||||
if (_retry_count == 0) {
|
||||
(void)_power->set_device_ready_urc_cb(mbed::callback(this, &CellularConnectionFSM::ready_urc_cb));
|
||||
}
|
||||
retry_state_or_fail();
|
||||
}
|
||||
}
|
||||
|
||||
void CellularConnectionFSM::state_sim_pin()
|
||||
{
|
||||
_cellularDevice->set_timeout(TIMEOUT_SIM_PIN);
|
||||
tr_info("Sim state (timeout %d ms)", TIMEOUT_SIM_PIN);
|
||||
if (open_sim()) {
|
||||
enter_to_state(STATE_REGISTERING_NETWORK);
|
||||
} else {
|
||||
retry_state_or_fail();
|
||||
}
|
||||
}
|
||||
|
||||
void CellularConnectionFSM::state_registering()
|
||||
{
|
||||
_cellularDevice->set_timeout(TIMEOUT_NETWORK);
|
||||
if (is_registered()) {
|
||||
// we are already registered, go to attach
|
||||
enter_to_state(STATE_ATTACHING_NETWORK);
|
||||
} else {
|
||||
bool auto_reg = false;
|
||||
nsapi_error_t err = is_automatic_registering(auto_reg);
|
||||
if (err == NSAPI_ERROR_OK && !auto_reg) { // when we support plmn add this : || plmn
|
||||
// automatic registering is not on, set registration and retry
|
||||
_cellularDevice->set_timeout(TIMEOUT_REGISTRATION);
|
||||
set_network_registration();
|
||||
}
|
||||
retry_state_or_fail();
|
||||
}
|
||||
}
|
||||
|
||||
void CellularConnectionFSM::state_attaching()
|
||||
{
|
||||
_cellularDevice->set_timeout(TIMEOUT_CONNECT);
|
||||
CellularNetwork::AttachStatus attach_status;
|
||||
if (get_attach_network(attach_status)) {
|
||||
if (attach_status == CellularNetwork::Attached) {
|
||||
enter_to_state(STATE_CONNECTING_NETWORK);
|
||||
} else {
|
||||
set_attach_network();
|
||||
retry_state_or_fail();
|
||||
}
|
||||
} else {
|
||||
retry_state_or_fail();
|
||||
}
|
||||
}
|
||||
|
||||
void CellularConnectionFSM::state_connect_to_network()
|
||||
{
|
||||
_cellularDevice->set_timeout(TIMEOUT_CONNECT);
|
||||
tr_info("Connect to cellular network (timeout %d ms)", TIMEOUT_CONNECT);
|
||||
if (_network->connect() == NSAPI_ERROR_OK) {
|
||||
_cellularDevice->set_timeout(TIMEOUT_NETWORK);
|
||||
tr_debug("Connected to cellular network, set at timeout (timeout %d ms)", TIMEOUT_NETWORK);
|
||||
// when using modems stack connect is synchronous
|
||||
_next_state = STATE_CONNECTED;
|
||||
} else {
|
||||
retry_state_or_fail();
|
||||
}
|
||||
}
|
||||
|
||||
void CellularConnectionFSM::state_connected()
|
||||
{
|
||||
_cellularDevice->set_timeout(TIMEOUT_NETWORK);
|
||||
tr_debug("Cellular ready! (timeout %d ms)", TIMEOUT_NETWORK);
|
||||
if (_status_callback) {
|
||||
_status_callback(_state, _next_state);
|
||||
}
|
||||
}
|
||||
|
||||
void CellularConnectionFSM::event()
|
||||
{
|
||||
nsapi_error_t err;
|
||||
int event_timeout = -1;
|
||||
|
||||
_event_timeout = -1;
|
||||
switch (_state) {
|
||||
case STATE_INIT:
|
||||
event_timeout = _start_time;
|
||||
tr_info("INIT state, waiting %d ms before POWER state)", _start_time);
|
||||
_next_state = STATE_POWER_ON;
|
||||
state_init();
|
||||
break;
|
||||
case STATE_POWER_ON:
|
||||
_cellularDevice->set_timeout(TIMEOUT_POWER_ON);
|
||||
tr_info("Cellular power ON (timeout %d ms)", TIMEOUT_POWER_ON);
|
||||
if (open_power(_serial)) {
|
||||
_next_state = STATE_DEVICE_READY;
|
||||
_retry_count = 0;
|
||||
} else {
|
||||
if (++_retry_count <= RETRY_COUNT_DEFAULT) {
|
||||
tr_warn("Power ON retry %d", _retry_count);
|
||||
event_timeout = 3 * 1000;
|
||||
} else {
|
||||
report_failure("Power");
|
||||
return;
|
||||
}
|
||||
}
|
||||
state_power_on();
|
||||
break;
|
||||
case STATE_DEVICE_READY:
|
||||
_cellularDevice->set_timeout(TIMEOUT_POWER_ON);
|
||||
if (_power->set_at_mode() == NSAPI_ERROR_OK) {
|
||||
tr_info("Cellular device ready");
|
||||
_next_state = STATE_SIM_PIN;
|
||||
_retry_count = 0;
|
||||
device_ready();
|
||||
} else {
|
||||
tr_info("Waiting for cellular device (retry %d/%d, timeout %d ms)", _retry_count, RETRY_COUNT_DEFAULT,
|
||||
TIMEOUT_POWER_ON);
|
||||
if (_retry_count++ <= RETRY_COUNT_DEFAULT) {
|
||||
event_timeout = 3 * 1000;
|
||||
} else {
|
||||
report_failure("Power");
|
||||
return;
|
||||
}
|
||||
}
|
||||
state_device_ready();
|
||||
break;
|
||||
case STATE_SIM_PIN:
|
||||
_cellularDevice->set_timeout(TIMEOUT_SIM_PIN);
|
||||
tr_info("Start cellular (timeout %d ms)", TIMEOUT_SIM_PIN);
|
||||
if (open_sim()) {
|
||||
_next_state = STATE_REGISTERING_NETWORK;
|
||||
_retry_count = 0;
|
||||
_state_retry_count = 0;
|
||||
tr_info("Check for network registration");
|
||||
} else {
|
||||
if (_retry_count++ <= RETRY_COUNT_DEFAULT) {
|
||||
tr_warn("Waiting for SIM %d/%d", _retry_count, RETRY_COUNT_DEFAULT);
|
||||
event_timeout = 3 * 1000;
|
||||
} else {
|
||||
report_failure("Entering SIM PIN");
|
||||
return;
|
||||
}
|
||||
}
|
||||
state_sim_pin();
|
||||
break;
|
||||
case STATE_REGISTERING_NETWORK:
|
||||
_cellularDevice->set_timeout(TIMEOUT_NETWORK);
|
||||
CellularNetwork::RegistrationStatus status;
|
||||
bool is_registered;
|
||||
_next_state = STATE_REGISTER_NETWORK;
|
||||
for (int type = 0; type < CellularNetwork::C_MAX; type++) {
|
||||
if (get_network_registration((CellularNetwork::RegistrationType) type, status, is_registered)) {
|
||||
tr_debug("get_network_registration: type=%d, status=%d", type, status);
|
||||
if (is_registered) {
|
||||
tr_info("Registered to cellular network (type %d, status %d)", type, status);
|
||||
_next_state = STATE_ATTACHING_NETWORK;
|
||||
_retry_count = 0;
|
||||
_state_retry_count = 0;
|
||||
event_timeout = 0;
|
||||
tr_info("Check cellular network attach state");
|
||||
break;
|
||||
} else {
|
||||
if (_retry_count < 180) {
|
||||
event_timeout = 1000;
|
||||
_next_state = STATE_REGISTERING_NETWORK;
|
||||
tr_info("Waiting for registration %d/180 (type %d, status %d)", _retry_count, type, status);
|
||||
} else {
|
||||
tr_info("Start cellular registration");
|
||||
_next_state = STATE_REGISTER_NETWORK;
|
||||
_retry_count = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_next_state == STATE_REGISTERING_NETWORK) {
|
||||
_retry_count++;
|
||||
}
|
||||
break;
|
||||
case STATE_REGISTER_NETWORK:
|
||||
_cellularDevice->set_timeout(TIMEOUT_REGISTRATION);
|
||||
tr_info("Register to cellular network (timeout %d ms)", TIMEOUT_REGISTRATION);
|
||||
if (set_network_registration()) {
|
||||
_next_state = STATE_REGISTERING_NETWORK;
|
||||
_retry_count = 0;
|
||||
if (_state_retry_count > RETRY_COUNT_DEFAULT) {
|
||||
report_failure("Registration retry");
|
||||
return;
|
||||
}
|
||||
_state_retry_count++;
|
||||
} else {
|
||||
if (_retry_count < _retry_array_length) {
|
||||
event_timeout = _retry_timeout_array[_retry_count] * 1000;
|
||||
_retry_count++;
|
||||
} else {
|
||||
report_failure("Registration");
|
||||
return;
|
||||
}
|
||||
}
|
||||
state_registering();
|
||||
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;
|
||||
_retry_count = 0;
|
||||
} else {
|
||||
_next_state = STATE_ATTACH_NETWORK;
|
||||
_retry_count = 0;
|
||||
}
|
||||
} else {
|
||||
if (_retry_count++ <= RETRY_COUNT_DEFAULT) {
|
||||
event_timeout = 1 * 1000;
|
||||
} else {
|
||||
report_failure("Attaching");
|
||||
return;
|
||||
}
|
||||
}
|
||||
state_attaching();
|
||||
break;
|
||||
case STATE_ATTACH_NETWORK:
|
||||
_cellularDevice->set_timeout(TIMEOUT_NETWORK);
|
||||
tr_info("Attach to cellular network (timeout %d ms)", TIMEOUT_NETWORK);
|
||||
if (set_attach_network()) {
|
||||
_next_state = STATE_ATTACHING_NETWORK;
|
||||
_retry_count = 0;
|
||||
if (_state_retry_count >= RETRY_COUNT_DEFAULT) {
|
||||
report_failure("Attach retry");
|
||||
return;
|
||||
}
|
||||
_state_retry_count++;
|
||||
tr_info("Cellular network attaching");
|
||||
} else {
|
||||
if (_retry_count < _retry_array_length) {
|
||||
event_timeout = _retry_timeout_array[_retry_count] * 1000;
|
||||
_retry_count++;
|
||||
} else {
|
||||
report_failure("Attach");
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case STATE_CONNECT_NETWORK:
|
||||
_cellularDevice->set_timeout(TIMEOUT_NETWORK);
|
||||
tr_info("Connect to cellular network (timeout %d ms)", TIMEOUT_NETWORK);
|
||||
err = _network->connect();
|
||||
if (!err) {
|
||||
_next_state = STATE_CONNECTED;
|
||||
} else {
|
||||
if (_retry_count < _retry_array_length) {
|
||||
event_timeout = _retry_timeout_array[_retry_count] * 1000;
|
||||
_retry_count++;
|
||||
} else {
|
||||
report_failure("Network Connect");
|
||||
return;
|
||||
}
|
||||
}
|
||||
case STATE_CONNECTING_NETWORK:
|
||||
state_connect_to_network();
|
||||
break;
|
||||
case STATE_CONNECTED:
|
||||
_cellularDevice->set_timeout(TIMEOUT_NETWORK);
|
||||
tr_debug("Cellular ready! (timeout %d ms)", TIMEOUT_NETWORK);
|
||||
if (_status_callback) {
|
||||
if (!_status_callback(_state, _next_state)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
state_connected();
|
||||
break;
|
||||
default:
|
||||
MBED_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
|
||||
if (_next_state != _state || event_timeout >= 0) {
|
||||
if (_next_state != _state || _event_timeout >= 0) {
|
||||
if (_next_state != _state) { // state exit condition
|
||||
tr_info("Cellular state from %d to %d", _state, _next_state);
|
||||
tr_info("Cellular state from %s to %s", get_state_string((CellularConnectionFSM::CellularState)_state),
|
||||
get_state_string((CellularConnectionFSM::CellularState)_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) {
|
||||
tr_info("Cellular event retry %d", retry_count);
|
||||
} else {
|
||||
report_failure("Cellular connection failed!");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
tr_info("Cellular event in %d milliseconds", event_timeout);
|
||||
}
|
||||
tr_info("Cellular event in %d seconds", _event_timeout);
|
||||
}
|
||||
_state = _next_state;
|
||||
if (event_timeout == -1) {
|
||||
event_timeout = 0;
|
||||
if (_event_timeout == -1) {
|
||||
_event_timeout = 0;
|
||||
}
|
||||
if (!_queue.call_in(event_timeout, callback(this, &CellularConnectionFSM::event))) {
|
||||
_event_id = _queue.call_in(_event_timeout*1000, callback(this, &CellularConnectionFSM::event));
|
||||
if (!_event_id) {
|
||||
report_failure("Cellular event failure!");
|
||||
return;
|
||||
}
|
||||
|
@ -493,12 +538,9 @@ void CellularConnectionFSM::event()
|
|||
|
||||
nsapi_error_t CellularConnectionFSM::start_dispatch()
|
||||
{
|
||||
tr_info("CellularConnectionUtil::start");
|
||||
tr_info("Create cellular thread");
|
||||
|
||||
MBED_ASSERT(!_queue_thread);
|
||||
|
||||
_queue_thread = new rtos::Thread;
|
||||
_queue_thread = new rtos::Thread(osPriorityNormal, 2048);
|
||||
if (!_queue_thread) {
|
||||
stop();
|
||||
return NSAPI_ERROR_NO_MEMORY;
|
||||
|
@ -508,21 +550,9 @@ nsapi_error_t CellularConnectionFSM::start_dispatch()
|
|||
return NSAPI_ERROR_NO_MEMORY;
|
||||
}
|
||||
|
||||
tr_info("CellularConnectionUtil::started");
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
void CellularConnectionFSM::stop()
|
||||
{
|
||||
tr_info("CellularConnectionUtil::stop");
|
||||
_cellularDevice->close_power();
|
||||
_cellularDevice->close_network();
|
||||
if (_queue_thread) {
|
||||
_queue_thread->terminate();
|
||||
_queue_thread = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void CellularConnectionFSM::set_serial(UARTSerial *serial)
|
||||
{
|
||||
_serial = serial;
|
||||
|
@ -533,6 +563,41 @@ void CellularConnectionFSM::set_callback(mbed::Callback<bool(int, int)> status_c
|
|||
_status_callback = status_callback;
|
||||
}
|
||||
|
||||
void CellularConnectionFSM::attach(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb)
|
||||
{
|
||||
_event_status_cb = status_cb;
|
||||
_network->attach(callback(this, &CellularConnectionFSM::network_callback));
|
||||
}
|
||||
|
||||
void CellularConnectionFSM::network_callback(nsapi_event_t ev, intptr_t ptr)
|
||||
{
|
||||
|
||||
tr_info("FSM: network_callback called with event: %d, intptr: %d", ev, ptr);
|
||||
if ((cellular_connection_status_t)ev == CellularRegistrationStatusChanged && _state == STATE_REGISTERING_NETWORK) {
|
||||
// expect packet data so only these states are valid
|
||||
if (ptr == CellularNetwork::RegisteredHomeNetwork && CellularNetwork::RegisteredRoaming) {
|
||||
_queue.cancel(_event_id);
|
||||
continue_from_state(STATE_ATTACHING_NETWORK);
|
||||
}
|
||||
}
|
||||
|
||||
if (_event_status_cb) {
|
||||
_event_status_cb(ev, ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void CellularConnectionFSM::ready_urc_cb()
|
||||
{
|
||||
tr_debug("Device ready URC func called");
|
||||
if (_state == STATE_DEVICE_READY && _power->set_at_mode() == NSAPI_ERROR_OK) {
|
||||
tr_debug("State was STATE_DEVICE_READY and at mode ready, cancel state and move to next");
|
||||
_queue.cancel(_event_id);
|
||||
if (device_ready()) {
|
||||
continue_from_state(STATE_SIM_PIN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
events::EventQueue *CellularConnectionFSM::get_queue()
|
||||
{
|
||||
return &_queue;
|
||||
|
|
|
@ -29,10 +29,9 @@
|
|||
#include "CellularNetwork.h"
|
||||
#include "CellularPower.h"
|
||||
#include "CellularSIM.h"
|
||||
#include "CellularUtil.h"
|
||||
|
||||
// modem type is defined as CELLULAR_DEVICE macro
|
||||
#define _CELLULAR_STRINGIFY(a) #a
|
||||
#define CELLULAR_STRINGIFY(a) _CELLULAR_STRINGIFY(a)
|
||||
#include CELLULAR_STRINGIFY(CELLULAR_DEVICE.h)
|
||||
|
||||
namespace mbed {
|
||||
|
@ -58,12 +57,10 @@ public:
|
|||
STATE_POWER_ON,
|
||||
STATE_DEVICE_READY,
|
||||
STATE_SIM_PIN,
|
||||
STATE_REGISTER_NETWORK,
|
||||
STATE_REGISTERING_NETWORK,
|
||||
STATE_ATTACH_NETWORK,
|
||||
STATE_ATTACHING_NETWORK,
|
||||
STATE_CONNECT_NETWORK,
|
||||
STATE_CONNECTED,
|
||||
STATE_CONNECTING_NETWORK,
|
||||
STATE_CONNECTED
|
||||
};
|
||||
|
||||
public:
|
||||
|
@ -83,6 +80,16 @@ public:
|
|||
*/
|
||||
void set_callback(mbed::Callback<bool(int, int)> status_callback);
|
||||
|
||||
/** Register callback for status reporting
|
||||
*
|
||||
* The specified status callback function will be called on status changes
|
||||
* on the network. The parameters on the callback are the event type and
|
||||
* event-type dependent reason parameter.
|
||||
*
|
||||
* @param status_cb The callback for status changes
|
||||
*/
|
||||
virtual void attach(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb);
|
||||
|
||||
/** Get event queue that can be chained to main event queue (or use start_dispatch)
|
||||
* @return event queue
|
||||
*/
|
||||
|
@ -131,28 +138,47 @@ public:
|
|||
*/
|
||||
void set_retry_timeout_array(uint16_t timeout[], int array_len);
|
||||
|
||||
const char* get_state_string(CellularState state);
|
||||
private:
|
||||
bool open_power(FileHandle *fh);
|
||||
bool power_on();
|
||||
bool open_sim();
|
||||
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();
|
||||
bool is_registered();
|
||||
bool device_ready();
|
||||
nsapi_error_t is_automatic_registering(bool& auto_reg);
|
||||
|
||||
// state functions to keep state machine simple
|
||||
void state_init();
|
||||
void state_power_on();
|
||||
void state_device_ready();
|
||||
void state_sim_pin();
|
||||
void state_registering();
|
||||
void state_attaching();
|
||||
void state_connect_to_network();
|
||||
void state_connected();
|
||||
void enter_to_state(CellularState state);
|
||||
void retry_state_or_fail();
|
||||
void network_callback(nsapi_event_t ev, intptr_t ptr);
|
||||
nsapi_error_t continue_from_state(CellularState state);
|
||||
|
||||
private:
|
||||
friend class EasyCellularConnection;
|
||||
NetworkStack *get_stack();
|
||||
|
||||
private:
|
||||
void device_ready();
|
||||
void report_failure(const char* msg);
|
||||
void event();
|
||||
void ready_urc_cb();
|
||||
|
||||
UARTSerial *_serial;
|
||||
CellularState _state;
|
||||
CellularState _next_state;
|
||||
|
||||
Callback<bool(int, int)> _status_callback;
|
||||
Callback<void(nsapi_event_t, intptr_t)> _event_status_cb;
|
||||
|
||||
CellularNetwork *_network;
|
||||
CellularPower *_power;
|
||||
|
@ -162,11 +188,14 @@ private:
|
|||
CellularDevice *_cellularDevice;
|
||||
char _sim_pin[PIN_SIZE+1];
|
||||
int _retry_count;
|
||||
int _state_retry_count;
|
||||
int _start_time;
|
||||
int _event_timeout;
|
||||
|
||||
uint16_t _retry_timeout_array[MAX_RETRY_ARRAY_SIZE];
|
||||
int _retry_array_length;
|
||||
events::EventQueue _at_queue;
|
||||
char _st_string[20];
|
||||
int _event_id;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -37,26 +37,35 @@ namespace mbed {
|
|||
|
||||
bool EasyCellularConnection::cellular_status(int state, int next_state)
|
||||
{
|
||||
tr_info("cellular_status %d=>%d", state, next_state);
|
||||
tr_info("cellular_status: %s ==> %s", _cellularConnectionFSM.get_state_string((CellularConnectionFSM::CellularState)state),
|
||||
_cellularConnectionFSM.get_state_string((CellularConnectionFSM::CellularState)next_state));
|
||||
|
||||
if (_target_state == state) {
|
||||
if (state == CellularConnectionFSM::STATE_CONNECTED) {
|
||||
tr_info("Target state reached: %s", _cellularConnectionFSM.get_state_string(_target_state));
|
||||
MBED_ASSERT(_cellularSemaphore.release() == osOK);
|
||||
return false; // return false -> state machine is halted
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void EasyCellularConnection::network_callback(nsapi_event_t ev, intptr_t ptr)
|
||||
{
|
||||
if (ev == NSAPI_EVENT_CONNECTION_STATUS_CHANGE) {
|
||||
if (ptr == NSAPI_STATUS_GLOBAL_UP) {
|
||||
_is_connected = true;
|
||||
} else {
|
||||
_is_connected = false;
|
||||
}
|
||||
tr_info("Target state reached: %d", _target_state);
|
||||
MBED_ASSERT(_cellularSemaphore.release() == osOK);
|
||||
return false;
|
||||
} else {
|
||||
_is_connected = false;
|
||||
}
|
||||
return true;
|
||||
if (_status_cb) {
|
||||
_status_cb(ev, ptr);
|
||||
}
|
||||
}
|
||||
|
||||
EasyCellularConnection::EasyCellularConnection(bool debug) :
|
||||
_is_connected(false), _is_initialized(false), _target_state(CellularConnectionFSM::STATE_POWER_ON), _cellularSerial(
|
||||
MDMTXD, MDMRXD, MBED_CONF_PLATFORM_DEFAULT_SERIAL_BAUD_RATE), _cellularSemaphore(0), _cellularConnectionFSM(), _credentials_err(
|
||||
NSAPI_ERROR_OK)
|
||||
NSAPI_ERROR_OK), _status_cb(0)
|
||||
{
|
||||
tr_info("EasyCellularConnection()");
|
||||
#if USE_APN_LOOKUP
|
||||
|
@ -84,6 +93,7 @@ nsapi_error_t EasyCellularConnection::init()
|
|||
|
||||
if (err == NSAPI_ERROR_OK) {
|
||||
err = _cellularConnectionFSM.start_dispatch();
|
||||
_cellularConnectionFSM.attach(callback(this, &EasyCellularConnection::network_callback));
|
||||
}
|
||||
_is_initialized = true;
|
||||
}
|
||||
|
@ -257,10 +267,7 @@ const char *EasyCellularConnection::get_gateway()
|
|||
|
||||
void EasyCellularConnection::attach(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb)
|
||||
{
|
||||
CellularNetwork *network = _cellularConnectionFSM.get_network();
|
||||
if (network) {
|
||||
network->attach(status_cb);
|
||||
}
|
||||
_status_cb = status_cb;
|
||||
}
|
||||
|
||||
void EasyCellularConnection::modem_debug_on(bool on)
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
*/
|
||||
|
||||
#ifndef EASY_CELLULAR_CONNECTION_H
|
||||
|
||||
#define EASY_CELLULAR_CONNECTION_H
|
||||
|
||||
#include "CellularConnectionFSM.h"
|
||||
|
@ -117,6 +116,10 @@ public:
|
|||
virtual const char *get_gateway();
|
||||
|
||||
/** Register callback for status reporting
|
||||
*
|
||||
* The specified status callback function will be called on status changes
|
||||
* on the network. The parameters on the callback are the event type and
|
||||
* event-type dependent reason parameter.
|
||||
*
|
||||
* @param status_cb The callback for status changes
|
||||
*/
|
||||
|
@ -142,6 +145,7 @@ private:
|
|||
* @return true to continue state machine
|
||||
*/
|
||||
bool cellular_status(int state, int next_state);
|
||||
void network_callback(nsapi_event_t ev, intptr_t ptr);
|
||||
nsapi_error_t init();
|
||||
nsapi_error_t check_connect();
|
||||
|
||||
|
@ -156,6 +160,7 @@ private:
|
|||
rtos::Semaphore _cellularSemaphore;
|
||||
CellularConnectionFSM _cellularConnectionFSM;
|
||||
nsapi_error_t _credentials_err;
|
||||
Callback<void(nsapi_event_t, intptr_t)> _status_cb;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -83,19 +83,19 @@ public:
|
|||
*/
|
||||
virtual void close_network() = 0;
|
||||
|
||||
/** Closes the opened CellularNetwork by deleting the CellularSMS instance.
|
||||
/** Closes the opened CellularSMS by deleting the CellularSMS instance.
|
||||
*/
|
||||
virtual void close_sms() = 0;
|
||||
|
||||
/** Closes the opened CellularNetwork by deleting the CellularPower instance.
|
||||
/** Closes the opened CellularPower by deleting the CellularPower instance.
|
||||
*/
|
||||
virtual void close_power() = 0;
|
||||
|
||||
/** Closes the opened CellularNetwork by deleting the CellularSIM instance.
|
||||
/** Closes the opened CellularSIM by deleting the CellularSIM instance.
|
||||
*/
|
||||
virtual void close_sim() = 0;
|
||||
|
||||
/** Closes the opened CellularNetwork by deleting the CellularInformation instance.
|
||||
/** Closes the opened CellularInformation by deleting the CellularInformation instance.
|
||||
*/
|
||||
virtual void close_information() = 0;
|
||||
|
||||
|
|
|
@ -116,16 +116,7 @@ public:
|
|||
CHAP
|
||||
};
|
||||
|
||||
// 3GPP TS 27.007 - 7.3 PLMN selection +COPS
|
||||
struct operator_t {
|
||||
enum Status {
|
||||
Unknown,
|
||||
Available,
|
||||
Current,
|
||||
Forbiden
|
||||
};
|
||||
|
||||
enum RadioAccessTechnology {
|
||||
enum RadioAccessTechnology {
|
||||
RAT_GSM,
|
||||
RAT_GSM_COMPACT,
|
||||
RAT_UTRAN,
|
||||
|
@ -139,6 +130,14 @@ public:
|
|||
RAT_UNKNOWN
|
||||
};
|
||||
|
||||
// 3GPP TS 27.007 - 7.3 PLMN selection +COPS
|
||||
struct operator_t {
|
||||
enum Status {
|
||||
Unknown,
|
||||
Available,
|
||||
Current,
|
||||
Forbiden
|
||||
};
|
||||
|
||||
Status op_status;
|
||||
char op_long[MAX_OPERATOR_NAME_LONG+1];
|
||||
|
@ -200,6 +199,23 @@ public:
|
|||
};
|
||||
typedef CellularList<pdpcontext_params_t> pdpContextList_t;
|
||||
|
||||
/* Network registering mode */
|
||||
enum NWRegisteringMode {
|
||||
NWModeAutomatic = 0, // automatic registering
|
||||
NWModeManual, // manual registering with plmn
|
||||
NWModeDeRegister, // deregister from network
|
||||
NWModeSetOnly, // set only <format> (for read command +COPS?), do not attempt registration/deregistration
|
||||
NWModeManualAutomatic // if manual fails, fallback to automatic
|
||||
};
|
||||
|
||||
|
||||
/** Does all the needed initializations that can fail
|
||||
*
|
||||
* @remark must be called immediately after constructor.
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t init() = 0;
|
||||
|
||||
/** Request registering to network.
|
||||
*
|
||||
* @param plmn format is in numeric format or 0 for automatic network registration
|
||||
|
@ -207,6 +223,24 @@ public:
|
|||
*/
|
||||
virtual nsapi_error_t set_registration(const char *plmn = 0) = 0;
|
||||
|
||||
/** Get the current network registering mode
|
||||
*
|
||||
* @param mode on successful return contains the current network registering mode
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t get_network_registering_mode(NWRegisteringMode& mode) = 0;
|
||||
|
||||
/** Activate/deactivate listening of network events for the given RegistrationType.
|
||||
* This should be called after network class is created and ready to receive AT commands.
|
||||
* After successful call network class starts to get information about network changes like
|
||||
* registration statue, access technology, cell id...
|
||||
*
|
||||
* @param type RegistrationType to set urc on/off
|
||||
* @param on Controls are urc' active or not
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t set_registration_urc(RegistrationType type, bool on) = 0;
|
||||
|
||||
/** Gets the network registration status.
|
||||
*
|
||||
* @param type see RegistrationType values
|
||||
|
@ -270,10 +304,17 @@ public:
|
|||
|
||||
/** Sets radio access technology.
|
||||
*
|
||||
* @param op_rat Radio access technology
|
||||
* @return zero on success
|
||||
* @param rat Radio access technology
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t set_access_technology(operator_t::RadioAccessTechnology op_rat) = 0;
|
||||
virtual nsapi_error_t set_access_technology(RadioAccessTechnology rat) = 0;
|
||||
|
||||
/** Get current radio access technology.
|
||||
*
|
||||
* @param rat Radio access technology
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t get_access_technology(RadioAccessTechnology& rat) = 0;
|
||||
|
||||
/** Scans for operators module can reach.
|
||||
*
|
||||
|
@ -317,6 +358,13 @@ public:
|
|||
virtual nsapi_error_t connect(const char *apn,
|
||||
const char *username = 0, const char *password = 0) = 0;
|
||||
|
||||
/** Finds the correct PDP context and activates it. If correct PDP context is not found, one is created.
|
||||
* Given APN (or not given) and stack type (IPv4/IPv6/dual) are influencing when finding the PDP context.
|
||||
*
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t activate_context() = 0;
|
||||
|
||||
/**
|
||||
* Set the pdn type to be used
|
||||
*
|
||||
|
|
|
@ -18,8 +18,10 @@
|
|||
#define CELLULAR_API_CELLULARPOWER_H_
|
||||
|
||||
#include "nsapi_types.h"
|
||||
#include "Callback.h"
|
||||
|
||||
namespace mbed {
|
||||
namespace mbed
|
||||
{
|
||||
|
||||
/**
|
||||
* Class CellularPower
|
||||
|
@ -118,6 +120,21 @@ public:
|
|||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t opt_receive_period(int mode, EDRXAccessTechnology act_type, uint8_t edrx_value) = 0;
|
||||
|
||||
/** Set URC callback function for device specific ready urc. URC is defined in device specific
|
||||
* power API. Used in startup sequence to listen when device is ready
|
||||
* for using at commands and possible sim.
|
||||
*
|
||||
* @param callback Callback function called when urc received
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t set_device_ready_urc_cb(mbed::Callback<void()> callback) = 0;
|
||||
|
||||
/** Removes the device ready urc from the list of urc's.
|
||||
*
|
||||
* @param callback callback to remove from the list of urc's
|
||||
*/
|
||||
virtual void remove_device_ready_urc_cb(mbed::Callback<void()> callback) = 0;
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
|
|
@ -88,17 +88,18 @@ ATHandler::ATHandler(FileHandle *fh, EventQueue &queue, int timeout, const char
|
|||
clear_error();
|
||||
|
||||
if (output_delimiter) {
|
||||
_output_delimiter_length = strlen(output_delimiter);
|
||||
_output_delimiter = new char[_output_delimiter_length];
|
||||
for (unsigned i=0; i<_output_delimiter_length; i++) {
|
||||
_output_delimiter[i] = output_delimiter[i];
|
||||
_output_delimiter = new char[strlen(output_delimiter) + 1];
|
||||
if (!_output_delimiter) {
|
||||
MBED_ASSERT(0);
|
||||
} else {
|
||||
memcpy(_output_delimiter, output_delimiter, strlen(output_delimiter) + 1);
|
||||
}
|
||||
} else {
|
||||
_output_delimiter = NULL;
|
||||
_output_delimiter_length = 0;
|
||||
_output_delimiter = NULL;
|
||||
}
|
||||
|
||||
reset_buffer();
|
||||
memset(_recv_buff, 0, sizeof(_recv_buff));
|
||||
memset(_info_resp_prefix, 0, sizeof(_info_resp_prefix));
|
||||
|
||||
_current_scope = NotSet;
|
||||
|
@ -153,21 +154,65 @@ void ATHandler::set_file_handle(FileHandle *fh)
|
|||
_fileHandle = fh;
|
||||
}
|
||||
|
||||
void ATHandler::set_urc_handler(const char *prefix, mbed::Callback<void()> callback)
|
||||
nsapi_error_t ATHandler::set_urc_handler(const char *prefix, mbed::Callback<void()> callback)
|
||||
{
|
||||
struct oob_t *oob = new struct oob_t;
|
||||
oob->matching_to_received = true;
|
||||
size_t prefix_len = strlen(prefix);
|
||||
if (prefix_len > _oob_string_max_length) {
|
||||
_oob_string_max_length = prefix_len;
|
||||
if (_oob_string_max_length > _max_resp_length) {
|
||||
_max_resp_length = _oob_string_max_length;
|
||||
}
|
||||
if (find_urc_handler(prefix, callback)) {
|
||||
tr_warn("URC already added with prefix: %s", prefix);
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
oob->prefix = prefix;
|
||||
oob->cb = callback;
|
||||
oob->next = _oobs;
|
||||
_oobs = oob;
|
||||
|
||||
struct oob_t *oob = new struct oob_t;
|
||||
if (!oob) {
|
||||
return NSAPI_ERROR_NO_MEMORY;
|
||||
} else {
|
||||
size_t prefix_len = strlen(prefix);
|
||||
if (prefix_len > _oob_string_max_length) {
|
||||
_oob_string_max_length = prefix_len;
|
||||
if (_oob_string_max_length > _max_resp_length) {
|
||||
_max_resp_length = _oob_string_max_length;
|
||||
}
|
||||
}
|
||||
|
||||
oob->prefix = prefix;
|
||||
oob->prefix_len = prefix_len;
|
||||
oob->cb = callback;
|
||||
oob->next = _oobs;
|
||||
_oobs = oob;
|
||||
}
|
||||
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
void ATHandler::remove_urc_handler(const char *prefix, mbed::Callback<void()> callback)
|
||||
{
|
||||
struct oob_t *current = _oobs;
|
||||
struct oob_t *prev = NULL;
|
||||
while (current) {
|
||||
if (strcmp(prefix, current->prefix) == 0 && current->cb == callback) {
|
||||
if (prev) {
|
||||
prev->next = current->next;
|
||||
} else {
|
||||
_oobs = current->next;
|
||||
}
|
||||
delete current;
|
||||
break;
|
||||
}
|
||||
prev = current;
|
||||
current = prev->next;
|
||||
}
|
||||
}
|
||||
|
||||
bool ATHandler::find_urc_handler(const char *prefix, mbed::Callback<void()> callback)
|
||||
{
|
||||
struct oob_t *oob = _oobs;
|
||||
while (oob) {
|
||||
if (strcmp(prefix, oob->prefix) == 0 && oob->cb == callback) {
|
||||
return true;
|
||||
}
|
||||
oob = oob->next;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ATHandler::event()
|
||||
|
@ -234,6 +279,7 @@ void ATHandler::process_oob()
|
|||
timer.start();
|
||||
do {
|
||||
if (match_urc()) {
|
||||
timer.reset();
|
||||
if (_fileHandle->readable() || (_recv_pos < _recv_len)) {
|
||||
continue;
|
||||
}
|
||||
|
@ -242,8 +288,10 @@ void ATHandler::process_oob()
|
|||
// If no match found, look for CRLF and consume everything up to CRLF
|
||||
if (mem_str(_recv_buff, _recv_len, CRLF, CRLF_LENGTH)) {
|
||||
consume_to_tag(CRLF, true);
|
||||
timer.reset();
|
||||
} else {
|
||||
if (_fileHandle->readable()) {
|
||||
timer.reset();
|
||||
fill_buffer();
|
||||
} else {
|
||||
#ifdef MBED_CONF_RTOS_PRESENT
|
||||
|
@ -251,7 +299,7 @@ void ATHandler::process_oob()
|
|||
#endif
|
||||
}
|
||||
}
|
||||
} while (timer.read_ms() < 20); // URC's are very short so 20ms should be enough
|
||||
} while (timer.read_ms() < 100); // URC's are very short
|
||||
}
|
||||
tr_debug("process_oob exit");
|
||||
|
||||
|
@ -272,7 +320,8 @@ void ATHandler::set_filehandle_sigio()
|
|||
void ATHandler::reset_buffer()
|
||||
{
|
||||
tr_debug("%s", __func__);
|
||||
_recv_pos = 0; _recv_len = 0;
|
||||
_recv_pos = 0;
|
||||
_recv_len = 0;
|
||||
}
|
||||
|
||||
void ATHandler::rewind_buffer()
|
||||
|
@ -438,7 +487,9 @@ ssize_t ATHandler::read_string(char *buf, size_t size, bool read_even_stop_tag)
|
|||
break;
|
||||
} else if (c == '\"') {
|
||||
match_pos = 0;
|
||||
len--;
|
||||
if (len > 0) {
|
||||
len--;
|
||||
}
|
||||
continue;
|
||||
} else if (_stop_tag->len && c == _stop_tag->tag[match_pos]) {
|
||||
match_pos++;
|
||||
|
@ -561,10 +612,10 @@ bool ATHandler::match_urc()
|
|||
rewind_buffer();
|
||||
size_t prefix_len = 0;
|
||||
for (struct oob_t *oob = _oobs; oob; oob = oob->next) {
|
||||
prefix_len = strlen(oob->prefix);
|
||||
prefix_len = oob->prefix_len;
|
||||
if (_recv_len >= prefix_len) {
|
||||
if (match(oob->prefix, prefix_len)) {
|
||||
tr_debug("URC! %s", oob->prefix);
|
||||
tr_debug("URC! %s\n", oob->prefix);
|
||||
set_scope(InfoType);
|
||||
if (oob->cb) {
|
||||
oob->cb();
|
||||
|
@ -651,11 +702,9 @@ void ATHandler::set_3gpp_error(int err, DeviceErrorType error_type)
|
|||
|
||||
void ATHandler::at_error(bool error_code_expected, DeviceErrorType error_type)
|
||||
{
|
||||
int32_t err = -1;
|
||||
|
||||
if (error_code_expected && (error_type == DeviceErrorTypeErrorCMS || error_type == DeviceErrorTypeErrorCME)) {
|
||||
set_scope(InfoType);
|
||||
err = read_int();
|
||||
int32_t err = read_int();
|
||||
|
||||
if (err != -1) {
|
||||
set_3gpp_error(err, error_type);
|
||||
|
@ -952,9 +1001,7 @@ void ATHandler::cmd_start(const char* cmd)
|
|||
}
|
||||
}
|
||||
|
||||
tr_debug("AT> %s", cmd);
|
||||
|
||||
|
||||
at_debug("AT cmd %s (err %d)\n", cmd, _last_err);
|
||||
|
||||
if (_last_err != NSAPI_ERROR_OK) {
|
||||
return;
|
||||
|
@ -967,7 +1014,7 @@ void ATHandler::cmd_start(const char* cmd)
|
|||
|
||||
void ATHandler::write_int(int32_t param)
|
||||
{
|
||||
tr_debug("write_int: %d", param);
|
||||
at_debug("AT int %d\n", param);
|
||||
// do common checks before sending subparameter
|
||||
if (check_cmd_send() == false) {
|
||||
return;
|
||||
|
@ -984,7 +1031,7 @@ void ATHandler::write_int(int32_t param)
|
|||
|
||||
void ATHandler::write_string(const char* param, bool useQuotations)
|
||||
{
|
||||
tr_debug("write_string: %s, %d", param, useQuotations);
|
||||
at_debug("AT str %s (with quotes %d)\n", param, useQuotations);
|
||||
// do common checks before sending subparameter
|
||||
if (check_cmd_send() == false) {
|
||||
return;
|
||||
|
@ -1005,37 +1052,43 @@ void ATHandler::write_string(const char* param, bool useQuotations)
|
|||
|
||||
void ATHandler::cmd_stop()
|
||||
{
|
||||
at_debug("AT stop %s (err %d)\n", _output_delimiter, _last_err);
|
||||
if (_last_err != NSAPI_ERROR_OK) {
|
||||
return;
|
||||
}
|
||||
// Finish with CR
|
||||
(void)write(_output_delimiter, _output_delimiter_length);
|
||||
(void)write(_output_delimiter, strlen(_output_delimiter));
|
||||
}
|
||||
|
||||
size_t ATHandler::write_bytes(const uint8_t *data, size_t len)
|
||||
{
|
||||
at_debug("AT write bytes %d (err %d)\n", len, _last_err);
|
||||
|
||||
if (_last_err != NSAPI_ERROR_OK) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t write_len = write(data, len);
|
||||
return write_len < 0 ? 0 : (size_t)write_len;
|
||||
return write(data, len);
|
||||
}
|
||||
|
||||
ssize_t ATHandler::write(const void *data, size_t len)
|
||||
size_t ATHandler::write(const void *data, size_t len)
|
||||
{
|
||||
pollfh fhs;
|
||||
fhs.fh = _fileHandle;
|
||||
fhs.events = POLLOUT;
|
||||
ssize_t write_len = -1;
|
||||
|
||||
int count = poll(&fhs, 1, _at_timeout);
|
||||
if (count > 0 && (fhs.revents & POLLOUT)) {
|
||||
write_len = _fileHandle->write(data, len);
|
||||
}
|
||||
|
||||
if (write_len < 0 || (size_t)write_len != len) {
|
||||
set_error(NSAPI_ERROR_DEVICE_ERROR);
|
||||
size_t write_len = 0;
|
||||
for (; write_len < len; ) {
|
||||
int count = poll(&fhs, 1, _at_timeout);
|
||||
if (count <= 0 || !(fhs.revents & POLLOUT)) {
|
||||
set_error(NSAPI_ERROR_DEVICE_ERROR);
|
||||
return 0;
|
||||
}
|
||||
ssize_t ret = _fileHandle->write((uint8_t*)data + write_len, len - write_len);
|
||||
if (ret < 0) {
|
||||
set_error(NSAPI_ERROR_DEVICE_ERROR);
|
||||
return 0;
|
||||
}
|
||||
write_len += (size_t)ret;
|
||||
}
|
||||
|
||||
return write_len;
|
||||
|
|
|
@ -29,7 +29,8 @@
|
|||
#include "Callback.h"
|
||||
#include "EventQueue.h"
|
||||
|
||||
namespace mbed {
|
||||
namespace mbed
|
||||
{
|
||||
|
||||
class FileHandle;
|
||||
|
||||
|
@ -106,11 +107,20 @@ public:
|
|||
nsapi_error_t unlock_return_error();
|
||||
|
||||
/** Set the urc callback for urc. If urc is found when parsing AT responses, then call if called.
|
||||
* If urc is already set then it's not set twice.
|
||||
*
|
||||
* @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
|
||||
* @return NSAPI_ERROR_OK or NSAPI_ERROR_NO_MEMORY if no memory
|
||||
*/
|
||||
nsapi_error_t set_urc_handler(const char *prefix, mbed::Callback<void()> callback);
|
||||
|
||||
/** Remove urc handler from linked list of urc's
|
||||
*
|
||||
* @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);
|
||||
void remove_urc_handler(const char *prefix, mbed::Callback<void()> callback);
|
||||
|
||||
ATHandler *_nextATHandler; // linked list
|
||||
|
||||
|
@ -184,16 +194,14 @@ private:
|
|||
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;
|
||||
int prefix_len;
|
||||
mbed::Callback<void()> cb;
|
||||
oob_t *next;
|
||||
};
|
||||
oob_t *_oobs;
|
||||
bool _response_terminated;
|
||||
uint32_t _at_timeout;
|
||||
uint32_t _previous_at_timeout;
|
||||
|
||||
|
@ -205,7 +213,7 @@ private:
|
|||
bool _processing;
|
||||
int32_t _ref_count;
|
||||
|
||||
//*************************************
|
||||
//*************************************
|
||||
public:
|
||||
|
||||
/** Starts the command writing by clearing the last error and writing the given command.
|
||||
|
@ -450,7 +458,7 @@ private:
|
|||
void set_3gpp_error(int err, DeviceErrorType error_type);
|
||||
|
||||
bool check_cmd_send();
|
||||
ssize_t write(const void *data, size_t len);
|
||||
size_t write(const void *data, size_t len);
|
||||
|
||||
/** Copy content of one char buffer to another buffer and sets NULL terminator
|
||||
*
|
||||
|
@ -471,6 +479,9 @@ private:
|
|||
* @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);
|
||||
|
||||
// check is urc is already added
|
||||
bool find_urc_handler(const char *prefix, mbed::Callback<void()> callback);
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
|
|
@ -41,7 +41,6 @@ AT_CellularDevice::~AT_CellularDevice()
|
|||
ATHandler *old = atHandler;
|
||||
atHandler = atHandler->_nextATHandler;
|
||||
delete old;
|
||||
old = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -90,7 +89,6 @@ void AT_CellularDevice::release_at_handler(ATHandler* at_handler)
|
|||
prev->_nextATHandler = atHandler->_nextATHandler;
|
||||
}
|
||||
delete atHandler;
|
||||
atHandler = NULL;
|
||||
break;
|
||||
} else {
|
||||
prev = atHandler;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "nsapi_ppp.h"
|
||||
#include "CellularUtil.h"
|
||||
#include "CellularLog.h"
|
||||
#include "CellularCommon.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace mbed_cellular_util;
|
||||
|
@ -28,21 +29,21 @@ using namespace mbed;
|
|||
struct at_reg_t {
|
||||
const CellularNetwork::RegistrationType type;
|
||||
const char *const cmd;
|
||||
const char *const urc_prefix;
|
||||
};
|
||||
|
||||
static const at_reg_t at_reg[] = {
|
||||
{ CellularNetwork::C_EREG, "AT+CEREG" },
|
||||
{ CellularNetwork::C_GREG, "AT+CGREG" },
|
||||
{ CellularNetwork::C_REG, "AT+CREG" },
|
||||
{ CellularNetwork::C_EREG, "AT+CEREG", "+CEREG:"},
|
||||
{ CellularNetwork::C_GREG, "AT+CGREG", "+CGREG:"},
|
||||
{ CellularNetwork::C_REG, "AT+CREG", "+CREG:"}
|
||||
};
|
||||
|
||||
AT_CellularNetwork::AT_CellularNetwork(ATHandler &atHandler) : AT_CellularBase(atHandler),
|
||||
_stack(NULL), _apn(NULL), _uname(NULL), _pwd(NULL), _ip_stack_type_requested(DEFAULT_STACK), _ip_stack_type(DEFAULT_STACK), _cid(-1),
|
||||
_connection_status_cb(NULL), _op_act(operator_t::RAT_UNKNOWN), _authentication_type(CHAP), _last_reg_type(C_REG),
|
||||
_connect_status(NSAPI_STATUS_DISCONNECTED), _new_context_set(false)
|
||||
_stack(NULL), _apn(NULL), _uname(NULL), _pwd(NULL), _ip_stack_type_requested(DEFAULT_STACK),
|
||||
_ip_stack_type(DEFAULT_STACK), _cid(-1), _connection_status_cb(NULL), _op_act(RAT_UNKNOWN),
|
||||
_authentication_type(CHAP), _cell_id(-1), _connect_status(NSAPI_STATUS_DISCONNECTED), _new_context_set(false),
|
||||
_is_context_active(false), _reg_status(NotRegistered), _current_act(RAT_UNKNOWN)
|
||||
{
|
||||
|
||||
_at.set_urc_handler("NO CARRIER", callback(this, &AT_CellularNetwork::urc_no_carrier));
|
||||
}
|
||||
|
||||
AT_CellularNetwork::~AT_CellularNetwork()
|
||||
|
@ -50,6 +51,23 @@ AT_CellularNetwork::~AT_CellularNetwork()
|
|||
free_credentials();
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::init()
|
||||
{
|
||||
_urc_funcs[C_EREG] = callback(this, &AT_CellularNetwork::urc_cereg);
|
||||
_urc_funcs[C_GREG] = callback(this, &AT_CellularNetwork::urc_cgreg);
|
||||
_urc_funcs[C_REG] = callback(this, &AT_CellularNetwork::urc_creg);
|
||||
|
||||
for (int type = 0; type < CellularNetwork::C_MAX; type++) {
|
||||
if (has_registration((RegistrationType)type)) {
|
||||
if (_at.set_urc_handler(at_reg[type].urc_prefix, _urc_funcs[type]) != NSAPI_ERROR_OK) {
|
||||
return NSAPI_ERROR_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _at.set_urc_handler("NO CARRIER", callback(this, &AT_CellularNetwork::urc_no_carrier));
|
||||
}
|
||||
|
||||
void AT_CellularNetwork::free_credentials()
|
||||
{
|
||||
if (_uname) {
|
||||
|
@ -73,6 +91,48 @@ void AT_CellularNetwork::urc_no_carrier()
|
|||
}
|
||||
}
|
||||
|
||||
void AT_CellularNetwork::read_reg_params_and_compare(RegistrationType type)
|
||||
{
|
||||
RegistrationStatus reg_status = NotRegistered;
|
||||
int lac = -1, cell_id = -1, act = -1;
|
||||
|
||||
read_reg_params(type, reg_status, lac, cell_id, act);
|
||||
|
||||
if (_at.get_last_error() == NSAPI_ERROR_OK && _connection_status_cb) {
|
||||
tr_debug("stat: %d, lac: %d, cellID: %d, act: %d", reg_status, lac, cell_id, act);
|
||||
if (act != -1 && (RadioAccessTechnology)act != _current_act) {
|
||||
_current_act = (RadioAccessTechnology)act;
|
||||
_connection_status_cb((nsapi_event_t)CellularRadioAccessTechnologyChanged, _current_act);
|
||||
}
|
||||
if (reg_status != _reg_status) {
|
||||
_reg_status = reg_status;
|
||||
_connection_status_cb((nsapi_event_t)CellularRegistrationStatusChanged, _reg_status);
|
||||
}
|
||||
if (cell_id != -1 && cell_id != _cell_id) {
|
||||
_cell_id = cell_id;
|
||||
_connection_status_cb((nsapi_event_t)CellularCellIDChanged, _cell_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AT_CellularNetwork::urc_creg()
|
||||
{
|
||||
tr_debug("urc_creg");
|
||||
read_reg_params_and_compare(C_REG);
|
||||
}
|
||||
|
||||
void AT_CellularNetwork::urc_cereg()
|
||||
{
|
||||
tr_debug("urc_cereg");
|
||||
read_reg_params_and_compare(C_EREG);
|
||||
}
|
||||
|
||||
void AT_CellularNetwork::urc_cgreg()
|
||||
{
|
||||
tr_debug("urc_cgreg");
|
||||
read_reg_params_and_compare(C_GREG);
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::set_credentials(const char *apn,
|
||||
const char *username, const char *password)
|
||||
{
|
||||
|
@ -149,15 +209,10 @@ nsapi_error_t AT_CellularNetwork::delete_current_context()
|
|||
return _at.get_last_error();
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::connect()
|
||||
nsapi_error_t AT_CellularNetwork::activate_context()
|
||||
{
|
||||
_at.lock();
|
||||
|
||||
_connect_status = NSAPI_STATUS_CONNECTING;
|
||||
if (_connection_status_cb) {
|
||||
_connection_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_CONNECTING);
|
||||
}
|
||||
|
||||
nsapi_error_t err = set_context_to_be_activated();
|
||||
if (err != NSAPI_ERROR_OK) {
|
||||
_at.unlock();
|
||||
|
@ -171,18 +226,58 @@ nsapi_error_t AT_CellularNetwork::connect()
|
|||
return err;
|
||||
}
|
||||
|
||||
err = open_data_channel();
|
||||
if (err != NSAPI_ERROR_OK) {
|
||||
// do check for stack to validate that we have support for stack
|
||||
_stack = get_stack();
|
||||
if (!_stack) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// If new PDP context was created and failed to activate, delete it
|
||||
if (_new_context_set) {
|
||||
delete_current_context();
|
||||
_is_context_active = false;
|
||||
_at.cmd_start("AT+CGACT?");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start("+CGACT:");
|
||||
while (_at.info_resp()) {
|
||||
int context_id = _at.read_int();
|
||||
int context_activation_state = _at.read_int();
|
||||
if (context_id == _cid && context_activation_state == 1) {
|
||||
_is_context_active = true;
|
||||
}
|
||||
}
|
||||
_at.resp_stop();
|
||||
|
||||
_at.unlock();
|
||||
if (!_is_context_active) {
|
||||
tr_info("Activate PDP context");
|
||||
_at.cmd_start("AT+CGACT=1,");
|
||||
_at.write_int(_cid);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
}
|
||||
|
||||
tr_error("Failed to open data channel!");
|
||||
err = (_at.get_last_error() == NSAPI_ERROR_OK) ? NSAPI_ERROR_OK : NSAPI_ERROR_NO_CONNECTION;
|
||||
|
||||
// If new PDP context was created and failed to activate, delete it
|
||||
if (err != NSAPI_ERROR_OK && _new_context_set) {
|
||||
delete_current_context();
|
||||
}
|
||||
|
||||
_at.unlock();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::connect()
|
||||
{
|
||||
_connect_status = NSAPI_STATUS_CONNECTING;
|
||||
if (_connection_status_cb) {
|
||||
_connection_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_CONNECTING);
|
||||
}
|
||||
|
||||
nsapi_error_t err = NSAPI_ERROR_OK;
|
||||
if (!_is_context_active) {
|
||||
err = activate_context();
|
||||
}
|
||||
if (err) {
|
||||
_connect_status = NSAPI_STATUS_DISCONNECTED;
|
||||
if (_connection_status_cb) {
|
||||
_connection_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_DISCONNECTED);
|
||||
|
@ -191,9 +286,19 @@ nsapi_error_t AT_CellularNetwork::connect()
|
|||
return err;
|
||||
}
|
||||
|
||||
#if NSAPI_PPP_AVAILABLE
|
||||
_at.lock();
|
||||
err = open_data_channel();
|
||||
_at.unlock();
|
||||
|
||||
#if !NSAPI_PPP_AVAILABLE
|
||||
if (err != NSAPI_ERROR_OK) {
|
||||
tr_error("Failed to open data channel!");
|
||||
_connect_status = NSAPI_STATUS_DISCONNECTED;
|
||||
if (_connection_status_cb) {
|
||||
_connection_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_DISCONNECTED);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
#else
|
||||
_connect_status = NSAPI_STATUS_GLOBAL_UP;
|
||||
if (_connection_status_cb) {
|
||||
_connection_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_GLOBAL_UP);
|
||||
|
@ -205,8 +310,6 @@ nsapi_error_t AT_CellularNetwork::connect()
|
|||
|
||||
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
|
||||
tr_info("Open data channel in PPP mode");
|
||||
_at.cmd_start("AT+CGDATA=\"PPP\",");
|
||||
|
@ -218,43 +321,12 @@ nsapi_error_t AT_CellularNetwork::open_data_channel()
|
|||
tr_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(), callback(this, &AT_CellularNetwork::ppp_status_cb), _uname, _pwd, _ip_stack_type);
|
||||
* If blocking: mbed_ppp_init() is a blocking call, it will block until
|
||||
connected, or timeout after 30 seconds*/
|
||||
return nsapi_ppp_connect(_at.get_file_handle(), callback(this, &AT_CellularNetwork::ppp_status_cb), NULL, NULL, _ip_stack_type);
|
||||
#else
|
||||
// do check for stack to validate that we have support for stack
|
||||
_stack = get_stack();
|
||||
if (!_stack) {
|
||||
return err;
|
||||
}
|
||||
|
||||
bool is_context_active = false;
|
||||
_at.cmd_start("AT+CGACT?");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start("+CGACT:");
|
||||
while (_at.info_resp()) {
|
||||
int context_id = _at.read_int();
|
||||
int context_activation_state = _at.read_int();
|
||||
if (context_id == _cid && context_activation_state == 1) {
|
||||
is_context_active = true;
|
||||
tr_debug("PDP context %d is active.", _cid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
_at.resp_stop();
|
||||
|
||||
if (!is_context_active) {
|
||||
tr_info("Activate PDP context %d", _cid);
|
||||
_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;
|
||||
return NSAPI_ERROR_OK;
|
||||
#endif // #if NSAPI_PPP_AVAILABLE
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -300,11 +372,10 @@ nsapi_error_t AT_CellularNetwork::set_blocking(bool blocking)
|
|||
#if NSAPI_PPP_AVAILABLE
|
||||
return nsapi_ppp_set_blocking(blocking);
|
||||
#else
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
return NSAPI_ERROR_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#if NSAPI_PPP_AVAILABLE
|
||||
void AT_CellularNetwork::ppp_status_cb(nsapi_event_t event, intptr_t parameter)
|
||||
{
|
||||
|
@ -316,8 +387,6 @@ void AT_CellularNetwork::ppp_status_cb(nsapi_event_t event, intptr_t parameter)
|
|||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::set_context_to_be_activated()
|
||||
{
|
||||
// try to find or create context with suitable stack
|
||||
|
@ -522,38 +591,47 @@ nsapi_ip_stack_t AT_CellularNetwork::string_to_stack_type(const char* pdp_type)
|
|||
return stack;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::set_registration_urc(bool urc_on)
|
||||
nsapi_error_t AT_CellularNetwork::set_registration_urc(RegistrationType type, bool urc_on)
|
||||
{
|
||||
for (unsigned int i = 0; i < sizeof(at_reg)/sizeof(at_reg[0]); i++) {
|
||||
if (has_registration(at_reg[i].type)) {
|
||||
_last_reg_type = at_reg[i].type;
|
||||
if (urc_on) {
|
||||
_at.cmd_start(at_reg[i].cmd);
|
||||
_at.write_string("=2", false);
|
||||
_at.cmd_stop();
|
||||
} else {
|
||||
_at.cmd_start(at_reg[i].cmd);
|
||||
_at.write_string("=0", false);
|
||||
_at.cmd_stop();
|
||||
}
|
||||
int index = (int)type;
|
||||
MBED_ASSERT(index >= 0 && index < C_MAX);
|
||||
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
if (!has_registration(type)) {
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
} else {
|
||||
_at.lock();
|
||||
if (urc_on) {
|
||||
_at.cmd_start(at_reg[index].cmd);
|
||||
_at.write_string("=2", false);
|
||||
_at.cmd_stop();
|
||||
} else {
|
||||
_at.cmd_start(at_reg[index].cmd);
|
||||
_at.write_string("=0", false);
|
||||
_at.cmd_stop();
|
||||
}
|
||||
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
return _at.unlock_return_error();
|
||||
}
|
||||
return _at.get_last_error();
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::get_network_registering_mode(NWRegisteringMode& mode)
|
||||
{
|
||||
_at.lock();
|
||||
_at.cmd_start("AT+COPS?");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start("+COPS:");
|
||||
mode = (NWRegisteringMode)_at.read_int();
|
||||
_at.resp_stop();
|
||||
|
||||
return _at.unlock_return_error();
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::set_registration(const char *plmn)
|
||||
{
|
||||
_at.lock();
|
||||
|
||||
nsapi_error_t ret = set_registration_urc(false);
|
||||
if (ret) {
|
||||
tr_error("Setting registration URC failed!");
|
||||
_at.clear_error(); // allow temporary failures here
|
||||
}
|
||||
|
||||
if (!plmn) {
|
||||
tr_debug("Automatic network registration");
|
||||
_at.cmd_start("AT+COPS?");
|
||||
|
@ -580,40 +658,13 @@ nsapi_error_t AT_CellularNetwork::set_registration(const char *plmn)
|
|||
return _at.unlock_return_error();
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::get_registration_status(RegistrationType type, RegistrationStatus &status)
|
||||
void AT_CellularNetwork::read_reg_params(RegistrationType type, RegistrationStatus ®_status, int &lac, int &cell_id, int &act)
|
||||
{
|
||||
int i = (int)type;
|
||||
MBED_ASSERT(i >= 0 && i < C_MAX);
|
||||
|
||||
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(at_reg[i].type)) {
|
||||
_at.unlock();
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
_at.cmd_start(at_reg[i].cmd);
|
||||
_at.write_string("=2", false);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
|
||||
_at.cmd_start(at_reg[i].cmd);
|
||||
_at.write_string("?", false);
|
||||
_at.cmd_stop();
|
||||
|
||||
_at.resp_start(rsp[i]);
|
||||
_at.read_int(); // ignore urc mode subparam
|
||||
status = (RegistrationStatus)_at.read_int();
|
||||
reg_status = (RegistrationStatus)_at.read_int();
|
||||
|
||||
int len = _at.read_string(lac_string, LAC_LENGTH);
|
||||
if (memcmp(lac_string, "ffff", LAC_LENGTH-1) && len >= 0) {
|
||||
|
@ -625,38 +676,55 @@ nsapi_error_t AT_CellularNetwork::get_registration_status(RegistrationType type,
|
|||
cell_id_read = true;
|
||||
}
|
||||
|
||||
_at.resp_stop();
|
||||
|
||||
_at.cmd_start(at_reg[i].cmd);
|
||||
_at.write_string("=0", false);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
nsapi_error_t ret = _at.get_last_error();
|
||||
_at.unlock();
|
||||
act = _at.read_int();
|
||||
|
||||
if (lac_read) {
|
||||
_lac = hex_str_to_int(lac_string, LAC_LENGTH);
|
||||
tr_debug("lac %s %d", lac_string, _lac );
|
||||
lac = hex_str_to_int(lac_string, LAC_LENGTH);
|
||||
tr_debug("lac %s %d", lac_string, lac );
|
||||
}
|
||||
|
||||
if (cell_id_read) {
|
||||
_cell_id = hex_str_to_int(cell_id_string, CELL_ID_LENGTH);
|
||||
tr_debug("cell_id %s %d", cell_id_string, _cell_id );
|
||||
cell_id = hex_str_to_int(cell_id_string, CELL_ID_LENGTH);
|
||||
tr_debug("cell_id %s %d", cell_id_string, cell_id );
|
||||
}
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::get_registration_status(RegistrationType type, RegistrationStatus &status)
|
||||
{
|
||||
int i = (int)type;
|
||||
MBED_ASSERT(i >= 0 && i < C_MAX);
|
||||
|
||||
if (!has_registration(at_reg[i].type)) {
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return ret;
|
||||
_at.lock();
|
||||
|
||||
const char *rsp[] = { "+CEREG:", "+CGREG:", "+CREG:"};
|
||||
_at.cmd_start(at_reg[i].cmd);
|
||||
_at.write_string("?", false);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start(rsp[i]);
|
||||
|
||||
(void)_at.read_int(); // ignore urc mode subparam
|
||||
int lac = -1, cell_id = -1, act = -1;
|
||||
read_reg_params(type, status, lac, cell_id, act);
|
||||
_at.resp_stop();
|
||||
_reg_status = status;
|
||||
|
||||
if (cell_id != -1) {
|
||||
_cell_id = cell_id;
|
||||
}
|
||||
if (act != -1) {
|
||||
_current_act = (RadioAccessTechnology)act;
|
||||
}
|
||||
|
||||
return _at.unlock_return_error();
|
||||
}
|
||||
|
||||
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;
|
||||
return _cell_id;
|
||||
}
|
||||
|
||||
bool AT_CellularNetwork::has_registration(RegistrationType reg_type)
|
||||
|
@ -702,13 +770,11 @@ nsapi_error_t AT_CellularNetwork::get_attach(AttachStatus &status)
|
|||
return _at.unlock_return_error();
|
||||
}
|
||||
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::get_apn_backoff_timer(int &backoff_timer)
|
||||
{
|
||||
_at.lock();
|
||||
|
||||
// If apn is set
|
||||
if (_apn) {
|
||||
_at.lock();
|
||||
_at.cmd_start("AT+CABTRDP=");
|
||||
_at.write_string(_apn);
|
||||
_at.cmd_stop();
|
||||
|
@ -718,9 +784,10 @@ nsapi_error_t AT_CellularNetwork::get_apn_backoff_timer(int &backoff_timer)
|
|||
backoff_timer = _at.read_int();
|
||||
}
|
||||
_at.resp_stop();
|
||||
return _at.unlock_return_error();
|
||||
}
|
||||
|
||||
return _at.unlock_return_error();
|
||||
return NSAPI_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
NetworkStack *AT_CellularNetwork::get_stack()
|
||||
|
@ -751,14 +818,12 @@ const char *AT_CellularNetwork::get_ip_address()
|
|||
|
||||
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()
|
||||
|
@ -775,14 +840,20 @@ bool AT_CellularNetwork::get_modem_stack_type(nsapi_ip_stack_t requested_stack)
|
|||
}
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::set_access_technology_impl(operator_t::RadioAccessTechnology opsAct)
|
||||
nsapi_error_t AT_CellularNetwork::set_access_technology_impl(RadioAccessTechnology opsAct)
|
||||
{
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::set_access_technology(operator_t::RadioAccessTechnology opAct)
|
||||
nsapi_error_t AT_CellularNetwork::get_access_technology(RadioAccessTechnology& rat)
|
||||
{
|
||||
if (opAct == operator_t::RAT_UNKNOWN) {
|
||||
rat = _current_act;
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularNetwork::set_access_technology(RadioAccessTechnology opAct)
|
||||
{
|
||||
if (opAct == RAT_UNKNOWN) {
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
@ -816,10 +887,10 @@ nsapi_error_t AT_CellularNetwork::scan_plmn(operList_t &operators, int &opsCount
|
|||
|
||||
// Optional - try read an int
|
||||
ret = _at.read_int();
|
||||
op->op_rat = (ret == error_code) ? operator_t::RAT_UNKNOWN:(operator_t::RadioAccessTechnology)ret;
|
||||
op->op_rat = (ret == error_code) ? RAT_UNKNOWN:(RadioAccessTechnology)ret;
|
||||
|
||||
if ((_op_act == operator_t::RAT_UNKNOWN) ||
|
||||
((op->op_rat != operator_t::RAT_UNKNOWN) && (op->op_rat == _op_act))) {
|
||||
if ((_op_act == RAT_UNKNOWN) ||
|
||||
((op->op_rat != RAT_UNKNOWN) && (op->op_rat == _op_act))) {
|
||||
idx++;
|
||||
} else {
|
||||
operators.delete_last();
|
||||
|
@ -1053,7 +1124,6 @@ int 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();
|
||||
|
@ -1066,22 +1136,18 @@ nsapi_error_t AT_CellularNetwork::get_operator_params(int &format, operator_t &o
|
|||
format = _at.read_int();
|
||||
|
||||
if (_at.get_last_error() == NSAPI_ERROR_OK) {
|
||||
|
||||
switch (format) {
|
||||
case 0:
|
||||
_at.read_string(operator_params.op_long, sizeof(operator_params.op_long));
|
||||
break;
|
||||
|
||||
case 1:
|
||||
_at.read_string(operator_params.op_short, sizeof(operator_params.op_short));
|
||||
break;
|
||||
|
||||
default:
|
||||
_at.read_string(operator_params.op_num, sizeof(operator_params.op_num));
|
||||
break;
|
||||
}
|
||||
|
||||
operator_params.op_rat = (operator_t::RadioAccessTechnology)_at.read_int();
|
||||
operator_params.op_rat = (RadioAccessTechnology)_at.read_int();
|
||||
}
|
||||
|
||||
_at.resp_stop();
|
||||
|
|
|
@ -60,8 +60,14 @@ protected:
|
|||
virtual NetworkStack *get_stack();
|
||||
|
||||
public: // CellularNetwork
|
||||
virtual nsapi_error_t init();
|
||||
|
||||
virtual nsapi_error_t activate_context();
|
||||
|
||||
virtual nsapi_error_t set_registration(const char *plmn = 0);
|
||||
|
||||
virtual nsapi_error_t get_network_registering_mode(NWRegisteringMode& mode);
|
||||
|
||||
virtual nsapi_error_t get_registration_status(RegistrationType type, RegistrationStatus &status);
|
||||
|
||||
virtual nsapi_error_t set_attach(int timeout = 10*1000);
|
||||
|
@ -81,7 +87,8 @@ public: // CellularNetwork
|
|||
|
||||
virtual const char *get_ip_address();
|
||||
|
||||
virtual nsapi_error_t set_access_technology(operator_t::RadioAccessTechnology op_rat);
|
||||
virtual nsapi_error_t set_access_technology(RadioAccessTechnology rat);
|
||||
virtual nsapi_error_t get_access_technology(RadioAccessTechnology& rat);
|
||||
|
||||
virtual nsapi_error_t scan_plmn(operList_t &operators, int &ops_count);
|
||||
|
||||
|
@ -107,6 +114,8 @@ public: // CellularNetwork
|
|||
|
||||
virtual nsapi_error_t get_operator_params(int &format, operator_t &operator_params);
|
||||
|
||||
virtual nsapi_error_t set_registration_urc(RegistrationType type, bool on);
|
||||
|
||||
protected:
|
||||
|
||||
/** Check if modem supports the given stack type.
|
||||
|
@ -128,11 +137,15 @@ protected:
|
|||
*
|
||||
* @return zero on success
|
||||
*/
|
||||
virtual nsapi_error_t set_access_technology_impl(operator_t::RadioAccessTechnology op_rat);
|
||||
virtual nsapi_error_t set_access_technology_impl(RadioAccessTechnology op_rat);
|
||||
|
||||
private:
|
||||
// "NO CARRIER" urc
|
||||
void urc_no_carrier();
|
||||
void urc_creg();
|
||||
void urc_cereg();
|
||||
void urc_cgreg();
|
||||
|
||||
nsapi_error_t set_context_to_be_activated();
|
||||
nsapi_ip_stack_t string_to_stack_type(const char* pdp_type);
|
||||
|
||||
|
@ -141,9 +154,12 @@ private:
|
|||
nsapi_error_t open_data_channel();
|
||||
bool get_context();
|
||||
bool set_new_context(int cid);
|
||||
nsapi_error_t set_registration_urc(bool on);
|
||||
|
||||
nsapi_error_t delete_current_context();
|
||||
|
||||
void read_reg_params_and_compare(RegistrationType type);
|
||||
void read_reg_params(RegistrationType type, RegistrationStatus ®_status, int &lac, int &cell_id, int &act);
|
||||
|
||||
#if NSAPI_PPP_AVAILABLE
|
||||
void ppp_status_cb(nsapi_event_t, intptr_t);
|
||||
#endif
|
||||
|
@ -157,13 +173,15 @@ protected:
|
|||
nsapi_ip_stack_t _ip_stack_type;
|
||||
int _cid;
|
||||
Callback<void(nsapi_event_t, intptr_t)> _connection_status_cb;
|
||||
operator_t::RadioAccessTechnology _op_act;
|
||||
RadioAccessTechnology _op_act;
|
||||
AuthenticationType _authentication_type;
|
||||
int _lac;
|
||||
int _cell_id;
|
||||
RegistrationType _last_reg_type;
|
||||
nsapi_connection_status_t _connect_status;
|
||||
bool _new_context_set;
|
||||
bool _is_context_active;
|
||||
RegistrationStatus _reg_status;
|
||||
RadioAccessTechnology _current_act;
|
||||
mbed::Callback<void()> _urc_funcs[C_MAX];
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "AT_CellularPower.h"
|
||||
#include "CellularUtil.h"
|
||||
#include "CellularLog.h"
|
||||
#include "CellularTargets.h"
|
||||
#include "nsapi_types.h"
|
||||
|
||||
static const int PSMTimerBits = 5;
|
||||
|
@ -231,3 +232,12 @@ nsapi_error_t AT_CellularPower::opt_receive_period(int mode, EDRXAccessTechnolog
|
|||
|
||||
return _at.unlock_return_error();
|
||||
}
|
||||
|
||||
nsapi_error_t AT_CellularPower::set_device_ready_urc_cb(mbed::Callback<void()> callback)
|
||||
{
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
void AT_CellularPower::remove_device_ready_urc_cb(mbed::Callback<void()> callback)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -48,6 +48,10 @@ public:
|
|||
virtual nsapi_error_t opt_power_save_mode(int periodic_time, int active_time);
|
||||
|
||||
virtual nsapi_error_t opt_receive_period(int mode, EDRXAccessTechnology act_type, uint8_t edrx_value);
|
||||
|
||||
virtual nsapi_error_t set_device_ready_urc_cb(mbed::Callback<void()> callback);
|
||||
|
||||
virtual void remove_device_ready_urc_cb(mbed::Callback<void()> callback);
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
|
|
@ -176,9 +176,6 @@ const int GSM_TO_ASCII_TABLE_SIZE = sizeof(gsm_to_ascii)/sizeof(gsm_to_ascii[0])
|
|||
AT_CellularSMS::AT_CellularSMS(ATHandler &at) : AT_CellularBase(at), _cb(0), _mode(CellularSMSMmodeText),
|
||||
_use_8bit_encoding(false), _sim_wait_time(0), _sms_message_ref_number(1), _sms_info(NULL)
|
||||
{
|
||||
/* URCs, handled out of band */
|
||||
_at.set_urc_handler("+CMTI:", callback(this, &AT_CellularSMS::cmti_urc));
|
||||
_at.set_urc_handler("+CMT:", callback(this, &AT_CellularSMS::cmt_urc));
|
||||
}
|
||||
|
||||
AT_CellularSMS::~AT_CellularSMS()
|
||||
|
@ -258,6 +255,11 @@ nsapi_error_t AT_CellularSMS::set_csdh(int show_header)
|
|||
|
||||
nsapi_error_t AT_CellularSMS::initialize(CellularSMSMmode mode)
|
||||
{
|
||||
if (_at.set_urc_handler("+CMTI:", callback(this, &AT_CellularSMS::cmti_urc)) ||
|
||||
_at.set_urc_handler("+CMT:", callback(this, &AT_CellularSMS::cmt_urc))) {
|
||||
return NSAPI_ERROR_NO_MEMORY;
|
||||
}
|
||||
|
||||
_at.lock();
|
||||
set_cnmi(); //set new SMS indication
|
||||
set_cmgf(mode); //set message format/PDU
|
||||
|
@ -350,8 +352,6 @@ char* AT_CellularSMS::create_pdu(const char* phone_number, const char* message,
|
|||
pdu[x++] = '0';
|
||||
}
|
||||
|
||||
// possible to use 16 bit identifier, can't be defined yet from outside
|
||||
bool use_16_bit_identifier = false;
|
||||
uint8_t udhlen = 0;
|
||||
// Length can be update after we have created PDU, store position for later use.
|
||||
int lengthPos = x;
|
||||
|
@ -361,34 +361,17 @@ char* AT_CellularSMS::create_pdu(const char* phone_number, const char* message,
|
|||
if (msg_parts > 1) { // concatenated, must use UDH
|
||||
// user data header length in chars
|
||||
pdu[x++] = '0';
|
||||
if (use_16_bit_identifier) {
|
||||
udhlen = 7; // udh length in chars (6) + udhl length in chars
|
||||
pdu[x++] = '6';
|
||||
} else {
|
||||
udhlen = 6; // udh length in chars (5) + udhl length in chars
|
||||
pdu[x++] = '5';
|
||||
}
|
||||
udhlen = 6; // udh length in chars (5) + udhl length in chars
|
||||
pdu[x++] = '5';
|
||||
// Information element identifier
|
||||
pdu[x++] = '0';
|
||||
if (use_16_bit_identifier) {
|
||||
pdu[x++] = '8';
|
||||
} else {
|
||||
pdu[x++] = '0';
|
||||
}
|
||||
pdu[x++] = '0';
|
||||
// Information element data length
|
||||
pdu[x++] = '0';
|
||||
if (use_16_bit_identifier) {
|
||||
pdu[x++] = '4';
|
||||
} else {
|
||||
pdu[x++] = '3';
|
||||
}
|
||||
pdu[x++] = '3';
|
||||
// A reference number (must be the same for all parts of the same larger messages)
|
||||
int_to_hex_str(_sms_message_ref_number&0xFF, pdu+x);
|
||||
x +=2;
|
||||
if (use_16_bit_identifier) {
|
||||
int_to_hex_str((_sms_message_ref_number>>16)&0xFF, pdu+x);
|
||||
x +=2;
|
||||
}
|
||||
// How many parts does this message have?
|
||||
int_to_hex_str(msg_parts, pdu+x);
|
||||
x +=2;
|
||||
|
@ -676,13 +659,13 @@ nsapi_size_or_error_t AT_CellularSMS::read_sms_from_index(int msg_index, char* b
|
|||
nsapi_size_or_error_t AT_CellularSMS::read_sms(sms_info_t* sms, char* buf, char* phone_num, char* time_stamp)
|
||||
{
|
||||
// +CMGR: <stat>,[<alpha>],<length><CR><LF><pdu>
|
||||
int index = -1;
|
||||
int index;
|
||||
if (sms->parts == sms->parts_added) {
|
||||
char *pdu; // we need a temp buffer as payload is hexencoded ---> can't use buf as it might be enough for message but not hexenconded pdu.
|
||||
int status = -1;
|
||||
int msg_len = 0;
|
||||
int status;
|
||||
int msg_len;
|
||||
index = 0;
|
||||
int pduSize = 0;
|
||||
int pduSize;
|
||||
|
||||
for (int i = 0; i < sms->parts; i++) {
|
||||
wait_ms(_sim_wait_time);
|
||||
|
@ -1210,13 +1193,16 @@ uint16_t AT_CellularSMS::pack_7_bit_gsm_and_hex(const char* str, uint16_t len, c
|
|||
uint8_t shift;
|
||||
char tmp;
|
||||
|
||||
if (len == 0) {
|
||||
return 0;
|
||||
}
|
||||
// convert to 7bit gsm first
|
||||
char* gsm_str = (char*)malloc(len);
|
||||
if (!gsm_str) {
|
||||
return 0;
|
||||
}
|
||||
for (uint16_t y = 0; y < len; y++) {
|
||||
for (int x=0; x < GSM_TO_ASCII_TABLE_SIZE; x++) {
|
||||
for (int x=0; x < GSM_TO_ASCII_TABLE_SIZE; x++) {
|
||||
if (gsm_to_ascii[x] == str[y]) {
|
||||
gsm_str[y] = x;
|
||||
}
|
||||
|
|
|
@ -68,7 +68,7 @@ const char * AT_CellularStack::get_ip_address()
|
|||
|
||||
// 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);
|
||||
(void)_at.read_string(_ip, PDP_IPV6_SIZE-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,6 +92,7 @@ nsapi_error_t AT_CellularStack::socket_open(nsapi_socket_t *handle, nsapi_protoc
|
|||
if (!_socket) {
|
||||
_socket = new CellularSocket*[max_socket_count];
|
||||
if (!_socket) {
|
||||
tr_error("No memory to open socket!");
|
||||
return NSAPI_ERROR_NO_SOCKET;
|
||||
}
|
||||
_socket_count = max_socket_count;
|
||||
|
@ -109,9 +110,11 @@ nsapi_error_t AT_CellularStack::socket_open(nsapi_socket_t *handle, nsapi_protoc
|
|||
}
|
||||
|
||||
if (index == -1) {
|
||||
tr_error("No socket found!");
|
||||
return NSAPI_ERROR_NO_SOCKET;
|
||||
}
|
||||
|
||||
tr_info("Socket open index: %d", index);
|
||||
// create local socket structure, socket on modem is created when app calls sendto/recvfrom
|
||||
_socket[index] = new CellularSocket;
|
||||
CellularSocket *psock;
|
||||
|
@ -135,31 +138,35 @@ nsapi_error_t AT_CellularStack::socket_close(nsapi_socket_t handle)
|
|||
return err;
|
||||
}
|
||||
int sock_id = socket->id;
|
||||
bool sock_created = socket->created;
|
||||
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) {
|
||||
if (_socket[i] == socket) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
tr_info("Close socket index: %d id: %d created: %d", index, sock_id, socket->created);
|
||||
|
||||
if (index == -1) {
|
||||
tr_error("No socket found to be closed");
|
||||
return err;
|
||||
}
|
||||
|
||||
_socket[index] = NULL;
|
||||
delete socket;
|
||||
err = NSAPI_ERROR_OK;
|
||||
|
||||
// Close the socket on the modem if it was created
|
||||
_at.lock();
|
||||
|
||||
err = socket_close_impl(sock_id);
|
||||
|
||||
if (sock_created) {
|
||||
err = socket_close_impl(sock_id);
|
||||
}
|
||||
_at.unlock();
|
||||
|
||||
delete socket;
|
||||
socket = NULL;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* 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_COMMON_
|
||||
#define CELLULAR_COMMON_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "nsapi_types.h"
|
||||
|
||||
/**
|
||||
* Cellular specific event changes.
|
||||
* Connect and disconnect are handled via NSAPI_EVENT_CONNECTION_STATUS_CHANGE
|
||||
*/
|
||||
typedef enum cellular_event_status {
|
||||
CellularDeviceReady = NSAPI_EVENT_CELLULAR_STATUS_BASE, /* Modem is powered and ready to receive commands. No additional info in callback intptr_t. */
|
||||
CellularSIMStatusChanged = NSAPI_EVENT_CELLULAR_STATUS_BASE + 1, /* SIM state changed, call SIM state. enum SimState as additional info callback intptr_t. See enum SimState in ../API/CellularSIM.h */
|
||||
CellularRegistrationStatusChanged = NSAPI_EVENT_CELLULAR_STATUS_BASE + 2, /* Registering status changed. enum RegistrationStatus as additional info callback intptr_t. See enum RegistrationStatus in ../API/CellularNetwork.h */
|
||||
CellularRegistrationTypeChanged = NSAPI_EVENT_CELLULAR_STATUS_BASE + 3, /* Registration type changed. enum RegistrationType as additional info callback intptr_t. See enum RegistrationType in ../API/CellularNetwork.h */
|
||||
CellularCellIDChanged = NSAPI_EVENT_CELLULAR_STATUS_BASE + 4, /* Network Cell ID have changed. int cellid as additional info callback intptr_t. */
|
||||
CellularRadioAccessTechnologyChanged = NSAPI_EVENT_CELLULAR_STATUS_BASE + 5, /* Network roaming status have changed. enum RadioAccessTechnology as additional info callback intptr_t. See enum RadioAccessTechnology in ../API/CellularNetwork.h */
|
||||
} cellular_connection_status_t;
|
||||
|
||||
#endif // CELLULAR_COMMON_
|
|
@ -168,7 +168,7 @@ void separate_ip_addresses(char* orig, char* ip, size_t ip_size, char* ip2, size
|
|||
if (ip2 && (ip2_size > strlen(temp))) {
|
||||
memcpy(ip2, temp, strlen(temp));
|
||||
ip2[strlen(temp)] = '\0';
|
||||
} else {
|
||||
} else if (ip2) {
|
||||
ip2[0] = '\0';
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -22,7 +22,7 @@ using namespace mbed;
|
|||
|
||||
QUECTEL_BC95_CellularNetwork::QUECTEL_BC95_CellularNetwork(ATHandler &atHandler) : AT_CellularNetwork(atHandler)
|
||||
{
|
||||
_op_act = operator_t::RAT_NB1;
|
||||
_op_act = RAT_NB1;
|
||||
}
|
||||
|
||||
QUECTEL_BC95_CellularNetwork::~QUECTEL_BC95_CellularNetwork()
|
||||
|
@ -47,11 +47,11 @@ 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)
|
||||
nsapi_error_t QUECTEL_BC95_CellularNetwork::set_access_technology_impl(RadioAccessTechnology opRat)
|
||||
{
|
||||
if (opRat != operator_t::RAT_NB1) {
|
||||
if (opRat != RAT_NB1) {
|
||||
//TODO: Set as unknown or force to NB1?
|
||||
_op_act = operator_t::RAT_UNKNOWN;
|
||||
_op_act = RAT_UNKNOWN;
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ public:
|
|||
protected:
|
||||
virtual NetworkStack *get_stack();
|
||||
|
||||
virtual nsapi_error_t set_access_technology_impl(operator_t::RadioAccessTechnology opRat);
|
||||
virtual nsapi_error_t set_access_technology_impl(RadioAccessTechnology opRat);
|
||||
|
||||
virtual bool get_modem_stack_type(nsapi_ip_stack_t requested_stack);
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "QUECTEL_BC95_CellularStack.h"
|
||||
#include "CellularUtil.h"
|
||||
#include "CellularLog.h"
|
||||
|
||||
using namespace mbed;
|
||||
using namespace mbed_cellular_util;
|
||||
|
@ -78,12 +79,14 @@ nsapi_error_t QUECTEL_BC95_CellularStack::socket_close_impl(int sock_id)
|
|||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
|
||||
tr_info("Close socket: %d error: %d", sock_id, _at.get_last_error());
|
||||
|
||||
return _at.get_last_error();
|
||||
}
|
||||
|
||||
nsapi_error_t QUECTEL_BC95_CellularStack::create_socket_impl(CellularSocket *socket)
|
||||
{
|
||||
int sock_id;
|
||||
int sock_id = -1;
|
||||
bool socketOpenWorking = false;
|
||||
|
||||
if (socket->proto == NSAPI_UDP) {
|
||||
|
@ -117,6 +120,7 @@ nsapi_error_t QUECTEL_BC95_CellularStack::create_socket_impl(CellularSocket *soc
|
|||
}
|
||||
|
||||
if (!socketOpenWorking) {
|
||||
tr_error("Socket create failed!");
|
||||
return NSAPI_ERROR_NO_SOCKET;
|
||||
}
|
||||
|
||||
|
@ -124,10 +128,13 @@ nsapi_error_t QUECTEL_BC95_CellularStack::create_socket_impl(CellularSocket *soc
|
|||
for (int i = 0; i < BC95_SOCKET_MAX; i++) {
|
||||
CellularSocket *sock = _socket[i];
|
||||
if (sock && sock->created && sock->id == sock_id) {
|
||||
tr_error("Duplicate socket index: %d created:%d, sock_id: %d", i, sock->created, sock_id);
|
||||
return NSAPI_ERROR_NO_SOCKET;
|
||||
}
|
||||
}
|
||||
|
||||
tr_info("Socket create id: %d", sock_id);
|
||||
|
||||
socket->id = sock_id;
|
||||
socket->created = true;
|
||||
|
||||
|
@ -139,9 +146,10 @@ nsapi_size_or_error_t QUECTEL_BC95_CellularStack::socket_sendto_impl(CellularSoc
|
|||
{
|
||||
int sent_len = 0;
|
||||
|
||||
char hexstr[BC95_MAX_PACKET_SIZE*2 + 1] = {0};
|
||||
char_str_to_hex_str((const char*)data, size, hexstr);
|
||||
|
||||
char *hexstr = new char[BC95_MAX_PACKET_SIZE*2+1];
|
||||
int hexlen = char_str_to_hex_str((const char*)data, size, hexstr);
|
||||
// NULL terminated for write_string
|
||||
hexstr[hexlen] = 0;
|
||||
_at.cmd_start("AT+NSOST=");
|
||||
_at.write_int(socket->id);
|
||||
_at.write_string(address.get_ip_address(), false);
|
||||
|
@ -155,6 +163,8 @@ nsapi_size_or_error_t QUECTEL_BC95_CellularStack::socket_sendto_impl(CellularSoc
|
|||
sent_len = _at.read_int();
|
||||
_at.resp_stop();
|
||||
|
||||
delete hexstr;
|
||||
|
||||
if (_at.get_last_error() == NSAPI_ERROR_OK) {
|
||||
return sent_len;
|
||||
}
|
||||
|
@ -168,7 +178,7 @@ nsapi_size_or_error_t QUECTEL_BC95_CellularStack::socket_recvfrom_impl(CellularS
|
|||
nsapi_size_or_error_t recv_len=0;
|
||||
int port;
|
||||
char ip_address[NSAPI_IP_SIZE];
|
||||
char hexstr[BC95_MAX_PACKET_SIZE*2 + 1];
|
||||
char *hexstr = new char[BC95_MAX_PACKET_SIZE*2+1];
|
||||
|
||||
_at.cmd_start("AT+NSORF=");
|
||||
_at.write_int(socket->id);
|
||||
|
@ -180,12 +190,13 @@ nsapi_size_or_error_t QUECTEL_BC95_CellularStack::socket_recvfrom_impl(CellularS
|
|||
_at.read_string(ip_address, sizeof(ip_address));
|
||||
port = _at.read_int();
|
||||
recv_len = _at.read_int();
|
||||
_at.read_string(hexstr, sizeof(hexstr));
|
||||
int hexlen = _at.read_string(hexstr, BC95_MAX_PACKET_SIZE*2+1);
|
||||
// remaining length
|
||||
_at.skip_param();
|
||||
_at.resp_stop();
|
||||
|
||||
if (!recv_len || (recv_len == -1) || (_at.get_last_error() != NSAPI_ERROR_OK)) {
|
||||
delete hexstr;
|
||||
return NSAPI_ERROR_WOULD_BLOCK;
|
||||
}
|
||||
|
||||
|
@ -194,9 +205,10 @@ nsapi_size_or_error_t QUECTEL_BC95_CellularStack::socket_recvfrom_impl(CellularS
|
|||
address->set_port(port);
|
||||
}
|
||||
|
||||
if (recv_len > 0) {
|
||||
hex_str_to_char_str((const char*) hexstr, recv_len*2, (char*)buffer);
|
||||
if (hexlen > 0) {
|
||||
hex_str_to_char_str((const char*) hexstr, hexlen, (char*)buffer);
|
||||
}
|
||||
|
||||
delete hexstr;
|
||||
return recv_len;
|
||||
}
|
||||
|
|
|
@ -20,15 +20,8 @@
|
|||
|
||||
#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
|
||||
namespace mbed
|
||||
{
|
||||
|
||||
class QUECTEL_BG96 : public AT_CellularDevice
|
||||
{
|
||||
|
|
|
@ -47,12 +47,12 @@ NetworkStack *QUECTEL_BG96_CellularNetwork::get_stack()
|
|||
return _stack;
|
||||
}
|
||||
|
||||
nsapi_error_t QUECTEL_BG96_CellularNetwork::set_access_technology_impl(operator_t::RadioAccessTechnology opsAct)
|
||||
nsapi_error_t QUECTEL_BG96_CellularNetwork::set_access_technology_impl(RadioAccessTechnology opsAct)
|
||||
{
|
||||
_at.lock();
|
||||
|
||||
switch (opsAct) {
|
||||
case operator_t::RAT_CATM1:
|
||||
case RAT_CATM1:
|
||||
_at.cmd_start("AT+QCFG=\"nwscanseq\",020301");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
|
@ -66,7 +66,7 @@ nsapi_error_t QUECTEL_BG96_CellularNetwork::set_access_technology_impl(operator_
|
|||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
break;
|
||||
case operator_t::RAT_NB1:
|
||||
case RAT_NB1:
|
||||
_at.cmd_start("AT+QCFG=\"nwscanseq\",030201");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
|
@ -80,10 +80,10 @@ nsapi_error_t QUECTEL_BG96_CellularNetwork::set_access_technology_impl(operator_
|
|||
_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:
|
||||
case RAT_GSM:
|
||||
case RAT_GSM_COMPACT:
|
||||
case RAT_UTRAN:
|
||||
case RAT_EGPRS:
|
||||
_at.cmd_start("AT+QCFG=\"nwscanseq\",010203");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
|
@ -107,7 +107,7 @@ nsapi_error_t QUECTEL_BG96_CellularNetwork::set_access_technology_impl(operator_
|
|||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
_at.unlock();
|
||||
_op_act = operator_t::RAT_UNKNOWN;
|
||||
_op_act = RAT_UNKNOWN;
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ public:
|
|||
protected:
|
||||
virtual NetworkStack *get_stack();
|
||||
|
||||
virtual nsapi_error_t set_access_technology_impl(operator_t::RadioAccessTechnology opRat);
|
||||
virtual nsapi_error_t set_access_technology_impl(RadioAccessTechnology opRat);
|
||||
|
||||
virtual bool get_modem_stack_type(nsapi_ip_stack_t requested_stack);
|
||||
};
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* 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 "QUECTEL_BG96_CellularPower.h"
|
||||
|
||||
#define DEVICE_READY_URC "CPIN:"
|
||||
|
||||
using namespace mbed;
|
||||
|
||||
QUECTEL_BG96_CellularPower::QUECTEL_BG96_CellularPower(ATHandler &atHandler) : AT_CellularPower(atHandler)
|
||||
{
|
||||
}
|
||||
|
||||
nsapi_error_t QUECTEL_BG96_CellularPower::set_device_ready_urc_cb(mbed::Callback<void()> callback)
|
||||
{
|
||||
return _at.set_urc_handler(DEVICE_READY_URC, callback);
|
||||
}
|
||||
|
||||
void QUECTEL_BG96_CellularPower::remove_device_ready_urc_cb(mbed::Callback<void()> callback)
|
||||
{
|
||||
_at.remove_urc_handler(DEVICE_READY_URC, callback);
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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 QUECTEL_BG96_CELLULAR_POWER_H_
|
||||
#define QUECTEL_BG96_CELLULAR_POWER_H_
|
||||
|
||||
#include "AT_CellularPower.h"
|
||||
|
||||
namespace mbed
|
||||
{
|
||||
|
||||
class QUECTEL_BG96_CellularPower : public AT_CellularPower
|
||||
{
|
||||
public:
|
||||
QUECTEL_BG96_CellularPower(ATHandler &atHandler);
|
||||
|
||||
public: //from CellularPower
|
||||
virtual nsapi_error_t set_device_ready_urc_cb(mbed::Callback<void()> callback);
|
||||
virtual void remove_device_ready_urc_cb(mbed::Callback<void()> callback);
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
||||
#endif // QUECTEL_BG96_CELLULAR_POWER_H_
|
|
@ -99,7 +99,7 @@ void QUECTEL_BG96_CellularStack::handle_open_socket_response(int &modem_connect_
|
|||
}
|
||||
nsapi_error_t QUECTEL_BG96_CellularStack::create_socket_impl(CellularSocket *socket)
|
||||
{
|
||||
int modem_connect_id;
|
||||
int modem_connect_id = -1;
|
||||
int request_connect_id = socket->id;
|
||||
int remote_port = 0;
|
||||
int err = -1;
|
||||
|
@ -246,7 +246,9 @@ nsapi_size_or_error_t QUECTEL_BG96_CellularStack::socket_recvfrom_impl(CellularS
|
|||
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);
|
||||
if (recv_len > 0) {
|
||||
_at.read_bytes((uint8_t*)buffer, recv_len);
|
||||
}
|
||||
_at.resp_stop();
|
||||
|
||||
if (!recv_len || (_at.get_last_error() != NSAPI_ERROR_OK)) {
|
||||
|
|
|
@ -37,8 +37,8 @@ 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)
|
||||
nsapi_error_t TELIT_HE910_CellularNetwork::set_access_technology_impl(RadioAccessTechnology opRat)
|
||||
{
|
||||
_op_act = operator_t::RAT_UNKNOWN;
|
||||
_op_act = RAT_UNKNOWN;
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ protected:
|
|||
|
||||
virtual bool has_registration(RegistrationType rat);
|
||||
|
||||
virtual nsapi_error_t set_access_technology_impl(operator_t::RadioAccessTechnology opRat);
|
||||
virtual nsapi_error_t set_access_technology_impl(RadioAccessTechnology opRat);
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
|
|
@ -37,8 +37,8 @@ bool UBLOX_PPP_CellularNetwork::has_registration(RegistrationType reg_type)
|
|||
return (reg_type == C_REG || reg_type == C_GREG);
|
||||
}
|
||||
|
||||
nsapi_error_t UBLOX_PPP_CellularNetwork::set_access_technology_impl(operator_t::RadioAccessTechnology opRat)
|
||||
nsapi_error_t UBLOX_PPP_CellularNetwork::set_access_technology_impl(RadioAccessTechnology opRat)
|
||||
{
|
||||
_op_act = operator_t::RAT_UNKNOWN;
|
||||
_op_act = RAT_UNKNOWN;
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ protected:
|
|||
|
||||
virtual bool has_registration(RegistrationType rat);
|
||||
|
||||
virtual nsapi_error_t set_access_technology_impl(operator_t::RadioAccessTechnology opRat);
|
||||
virtual nsapi_error_t set_access_technology_impl(RadioAccessTechnology opRat);
|
||||
};
|
||||
|
||||
MBED_DEPRECATED_SINCE("mbed-os-5.9", "This API will be deprecated, Use UBLOX_PPP_CellularNetwork instead of UBLOX_LISA_U_CellularNetwork.")
|
||||
|
|
|
@ -73,13 +73,15 @@ enum nsapi_error {
|
|||
|
||||
|
||||
/** Enum of event types
|
||||
*
|
||||
*
|
||||
* Event callbacks are accompanied with an event-dependent parameter passed as an intptr_t.
|
||||
*
|
||||
* @enum nsapi_event
|
||||
*/
|
||||
typedef enum nsapi_event {
|
||||
NSAPI_EVENT_CONNECTION_STATUS_CHANGE = 0 /*!< network connection status has changed, the parameter = new status (nsapi_connection_status_t) */
|
||||
NSAPI_EVENT_CONNECTION_STATUS_CHANGE = 0, /*!< network connection status has changed, the parameter = new status (nsapi_connection_status_t) */
|
||||
NSAPI_EVENT_CELLULAR_STATUS_BASE = 0x1000, /*!< Cellular modem status has changed, See the enum values from enum cellular_connection_status_t in /features/cellular/framework/common/CellularCommon.h */
|
||||
NSAPI_EVENT_CELLULAR_STATUS_END = 0x1FFF /*!< cellular modem status has changed, See the enum values from enum cellular_connection_status_t in /features/cellular/framework/common/CellularCommon.h */
|
||||
} nsapi_event_t;
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue