takashi kadono / Mbed OS Nucleo446_SSD1331

Dependencies:   ssd1331

Committer:
kadonotakashi
Date:
Wed Oct 10 00:33:53 2018 +0000
Revision:
0:8fdf9a60065b
how to make mbed librry

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kadonotakashi 0:8fdf9a60065b 1 /*
kadonotakashi 0:8fdf9a60065b 2 * Copyright (c) 2017, Arm Limited and affiliates.
kadonotakashi 0:8fdf9a60065b 3 * SPDX-License-Identifier: Apache-2.0
kadonotakashi 0:8fdf9a60065b 4 *
kadonotakashi 0:8fdf9a60065b 5 * Licensed under the Apache License, Version 2.0 (the "License");
kadonotakashi 0:8fdf9a60065b 6 * you may not use this file except in compliance with the License.
kadonotakashi 0:8fdf9a60065b 7 * You may obtain a copy of the License at
kadonotakashi 0:8fdf9a60065b 8 *
kadonotakashi 0:8fdf9a60065b 9 * http://www.apache.org/licenses/LICENSE-2.0
kadonotakashi 0:8fdf9a60065b 10 *
kadonotakashi 0:8fdf9a60065b 11 * Unless required by applicable law or agreed to in writing, software
kadonotakashi 0:8fdf9a60065b 12 * distributed under the License is distributed on an "AS IS" BASIS,
kadonotakashi 0:8fdf9a60065b 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
kadonotakashi 0:8fdf9a60065b 14 * See the License for the specific language governing permissions and
kadonotakashi 0:8fdf9a60065b 15 * limitations under the License.
kadonotakashi 0:8fdf9a60065b 16 */
kadonotakashi 0:8fdf9a60065b 17
kadonotakashi 0:8fdf9a60065b 18 #include "CellularConnectionFSM.h"
kadonotakashi 0:8fdf9a60065b 19
kadonotakashi 0:8fdf9a60065b 20 #ifdef CELLULAR_DEVICE
kadonotakashi 0:8fdf9a60065b 21
kadonotakashi 0:8fdf9a60065b 22 #ifndef MBED_TRACE_MAX_LEVEL
kadonotakashi 0:8fdf9a60065b 23 #define MBED_TRACE_MAX_LEVEL TRACE_LEVEL_INFO
kadonotakashi 0:8fdf9a60065b 24 #endif
kadonotakashi 0:8fdf9a60065b 25 #include "CellularLog.h"
kadonotakashi 0:8fdf9a60065b 26 #include "CellularCommon.h"
kadonotakashi 0:8fdf9a60065b 27 #include "CellularDevice.h"
kadonotakashi 0:8fdf9a60065b 28 #include "CellularUtil.h"
kadonotakashi 0:8fdf9a60065b 29
kadonotakashi 0:8fdf9a60065b 30 // timeout to wait for AT responses
kadonotakashi 0:8fdf9a60065b 31 #define TIMEOUT_POWER_ON (1*1000)
kadonotakashi 0:8fdf9a60065b 32 #define TIMEOUT_SIM_PIN (1*1000)
kadonotakashi 0:8fdf9a60065b 33 #define TIMEOUT_NETWORK (10*1000)
kadonotakashi 0:8fdf9a60065b 34 #define TIMEOUT_CONNECT (60*1000)
kadonotakashi 0:8fdf9a60065b 35 #define TIMEOUT_REGISTRATION (180*1000)
kadonotakashi 0:8fdf9a60065b 36
kadonotakashi 0:8fdf9a60065b 37 // maximum time when retrying network register, attach and connect in seconds ( 20minutes )
kadonotakashi 0:8fdf9a60065b 38 #define TIMEOUT_NETWORK_MAX (20*60)
kadonotakashi 0:8fdf9a60065b 39
kadonotakashi 0:8fdf9a60065b 40 #define RETRY_COUNT_DEFAULT 3
kadonotakashi 0:8fdf9a60065b 41
kadonotakashi 0:8fdf9a60065b 42 namespace mbed {
kadonotakashi 0:8fdf9a60065b 43
kadonotakashi 0:8fdf9a60065b 44 CellularConnectionFSM::CellularConnectionFSM() :
kadonotakashi 0:8fdf9a60065b 45 _serial(0), _state(STATE_INIT), _next_state(_state), _status_callback(0), _event_status_cb(0), _network(0), _power(0), _sim(0),
kadonotakashi 0:8fdf9a60065b 46 _queue(8 * EVENTS_EVENT_SIZE), _queue_thread(0), _cellularDevice(0), _retry_count(0), _event_timeout(-1),
kadonotakashi 0:8fdf9a60065b 47 _at_queue(0), _event_id(0), _plmn(0), _command_success(false), _plmn_network_found(false)
kadonotakashi 0:8fdf9a60065b 48 {
kadonotakashi 0:8fdf9a60065b 49 memset(_sim_pin, 0, sizeof(_sim_pin));
kadonotakashi 0:8fdf9a60065b 50 #if MBED_CONF_CELLULAR_RANDOM_MAX_START_DELAY == 0
kadonotakashi 0:8fdf9a60065b 51 _start_time = 0;
kadonotakashi 0:8fdf9a60065b 52 #else
kadonotakashi 0:8fdf9a60065b 53 // so that not every device don't start at the exact same time (for example after power outage)
kadonotakashi 0:8fdf9a60065b 54 _start_time = rand() % (MBED_CONF_CELLULAR_RANDOM_MAX_START_DELAY);
kadonotakashi 0:8fdf9a60065b 55 #endif // MBED_CONF_CELLULAR_RANDOM_MAX_START_DELAY
kadonotakashi 0:8fdf9a60065b 56
kadonotakashi 0:8fdf9a60065b 57 // set initial retry values in seconds
kadonotakashi 0:8fdf9a60065b 58 _retry_timeout_array[0] = 1; // double time on each retry in order to keep network happy
kadonotakashi 0:8fdf9a60065b 59 _retry_timeout_array[1] = 2;
kadonotakashi 0:8fdf9a60065b 60 _retry_timeout_array[2] = 4;
kadonotakashi 0:8fdf9a60065b 61 _retry_timeout_array[3] = 8;
kadonotakashi 0:8fdf9a60065b 62 _retry_timeout_array[4] = 16;
kadonotakashi 0:8fdf9a60065b 63 _retry_timeout_array[5] = 32;
kadonotakashi 0:8fdf9a60065b 64 _retry_timeout_array[6] = 64;
kadonotakashi 0:8fdf9a60065b 65 _retry_timeout_array[7] = 128; // if around two minutes was not enough then let's wait much longer
kadonotakashi 0:8fdf9a60065b 66 _retry_timeout_array[8] = 600;
kadonotakashi 0:8fdf9a60065b 67 _retry_timeout_array[9] = TIMEOUT_NETWORK_MAX;
kadonotakashi 0:8fdf9a60065b 68 _retry_array_length = MAX_RETRY_ARRAY_SIZE;
kadonotakashi 0:8fdf9a60065b 69 }
kadonotakashi 0:8fdf9a60065b 70
kadonotakashi 0:8fdf9a60065b 71 CellularConnectionFSM::~CellularConnectionFSM()
kadonotakashi 0:8fdf9a60065b 72 {
kadonotakashi 0:8fdf9a60065b 73 stop();
kadonotakashi 0:8fdf9a60065b 74 }
kadonotakashi 0:8fdf9a60065b 75
kadonotakashi 0:8fdf9a60065b 76 void CellularConnectionFSM::stop()
kadonotakashi 0:8fdf9a60065b 77 {
kadonotakashi 0:8fdf9a60065b 78 _queue.cancel(_event_id);
kadonotakashi 0:8fdf9a60065b 79 _queue.break_dispatch();
kadonotakashi 0:8fdf9a60065b 80
kadonotakashi 0:8fdf9a60065b 81 if (_queue_thread) {
kadonotakashi 0:8fdf9a60065b 82 _queue_thread->terminate();
kadonotakashi 0:8fdf9a60065b 83 delete _queue_thread;
kadonotakashi 0:8fdf9a60065b 84 _queue_thread = NULL;
kadonotakashi 0:8fdf9a60065b 85 }
kadonotakashi 0:8fdf9a60065b 86
kadonotakashi 0:8fdf9a60065b 87 if (_power) {
kadonotakashi 0:8fdf9a60065b 88 _cellularDevice->close_power();
kadonotakashi 0:8fdf9a60065b 89 _power = NULL;
kadonotakashi 0:8fdf9a60065b 90 }
kadonotakashi 0:8fdf9a60065b 91
kadonotakashi 0:8fdf9a60065b 92 if (_network) {
kadonotakashi 0:8fdf9a60065b 93 _cellularDevice->close_network();
kadonotakashi 0:8fdf9a60065b 94 _network = NULL;
kadonotakashi 0:8fdf9a60065b 95 }
kadonotakashi 0:8fdf9a60065b 96
kadonotakashi 0:8fdf9a60065b 97 if (_sim) {
kadonotakashi 0:8fdf9a60065b 98 _cellularDevice->close_sim();
kadonotakashi 0:8fdf9a60065b 99 _sim = NULL;
kadonotakashi 0:8fdf9a60065b 100 }
kadonotakashi 0:8fdf9a60065b 101
kadonotakashi 0:8fdf9a60065b 102 _state = STATE_INIT;
kadonotakashi 0:8fdf9a60065b 103 _next_state = _state;
kadonotakashi 0:8fdf9a60065b 104 }
kadonotakashi 0:8fdf9a60065b 105
kadonotakashi 0:8fdf9a60065b 106 nsapi_error_t CellularConnectionFSM::init()
kadonotakashi 0:8fdf9a60065b 107 {
kadonotakashi 0:8fdf9a60065b 108 tr_info("CELLULAR_DEVICE: %s", CELLULAR_STRINGIFY(CELLULAR_DEVICE));
kadonotakashi 0:8fdf9a60065b 109 _cellularDevice = CellularDevice::get_default_instance();
kadonotakashi 0:8fdf9a60065b 110 if (!_cellularDevice) {
kadonotakashi 0:8fdf9a60065b 111 stop();
kadonotakashi 0:8fdf9a60065b 112 return NSAPI_ERROR_NO_MEMORY;
kadonotakashi 0:8fdf9a60065b 113 }
kadonotakashi 0:8fdf9a60065b 114
kadonotakashi 0:8fdf9a60065b 115 _power = _cellularDevice->open_power(_serial);
kadonotakashi 0:8fdf9a60065b 116 if (!_power) {
kadonotakashi 0:8fdf9a60065b 117 stop();
kadonotakashi 0:8fdf9a60065b 118 return NSAPI_ERROR_NO_MEMORY;
kadonotakashi 0:8fdf9a60065b 119 }
kadonotakashi 0:8fdf9a60065b 120
kadonotakashi 0:8fdf9a60065b 121 _network = _cellularDevice->open_network(_serial);
kadonotakashi 0:8fdf9a60065b 122 if (!_network) {
kadonotakashi 0:8fdf9a60065b 123 stop();
kadonotakashi 0:8fdf9a60065b 124 return NSAPI_ERROR_NO_MEMORY;
kadonotakashi 0:8fdf9a60065b 125 }
kadonotakashi 0:8fdf9a60065b 126
kadonotakashi 0:8fdf9a60065b 127 _sim = _cellularDevice->open_sim(_serial);
kadonotakashi 0:8fdf9a60065b 128 if (!_sim) {
kadonotakashi 0:8fdf9a60065b 129 stop();
kadonotakashi 0:8fdf9a60065b 130 return NSAPI_ERROR_NO_MEMORY;
kadonotakashi 0:8fdf9a60065b 131 }
kadonotakashi 0:8fdf9a60065b 132
kadonotakashi 0:8fdf9a60065b 133 _at_queue = _cellularDevice->get_queue();
kadonotakashi 0:8fdf9a60065b 134 _at_queue->chain(&_queue);
kadonotakashi 0:8fdf9a60065b 135
kadonotakashi 0:8fdf9a60065b 136 _retry_count = 0;
kadonotakashi 0:8fdf9a60065b 137 _state = STATE_INIT;
kadonotakashi 0:8fdf9a60065b 138 _next_state = STATE_INIT;
kadonotakashi 0:8fdf9a60065b 139
kadonotakashi 0:8fdf9a60065b 140 return _network->init();
kadonotakashi 0:8fdf9a60065b 141 }
kadonotakashi 0:8fdf9a60065b 142
kadonotakashi 0:8fdf9a60065b 143 bool CellularConnectionFSM::power_on()
kadonotakashi 0:8fdf9a60065b 144 {
kadonotakashi 0:8fdf9a60065b 145 nsapi_error_t err = _power->on();
kadonotakashi 0:8fdf9a60065b 146 if (err != NSAPI_ERROR_OK && err != NSAPI_ERROR_UNSUPPORTED) {
kadonotakashi 0:8fdf9a60065b 147 tr_warn("Cellular start failed. Power off/on.");
kadonotakashi 0:8fdf9a60065b 148 err = _power->off();
kadonotakashi 0:8fdf9a60065b 149 if (err != NSAPI_ERROR_OK && err != NSAPI_ERROR_UNSUPPORTED) {
kadonotakashi 0:8fdf9a60065b 150 tr_error("Cellular power down failing after failed power up attempt!");
kadonotakashi 0:8fdf9a60065b 151 }
kadonotakashi 0:8fdf9a60065b 152 return false;
kadonotakashi 0:8fdf9a60065b 153 }
kadonotakashi 0:8fdf9a60065b 154 return true;
kadonotakashi 0:8fdf9a60065b 155 }
kadonotakashi 0:8fdf9a60065b 156
kadonotakashi 0:8fdf9a60065b 157 void CellularConnectionFSM::set_sim_pin(const char *sim_pin)
kadonotakashi 0:8fdf9a60065b 158 {
kadonotakashi 0:8fdf9a60065b 159 strncpy(_sim_pin, sim_pin, sizeof(_sim_pin));
kadonotakashi 0:8fdf9a60065b 160 _sim_pin[sizeof(_sim_pin) - 1] = '\0';
kadonotakashi 0:8fdf9a60065b 161 }
kadonotakashi 0:8fdf9a60065b 162
kadonotakashi 0:8fdf9a60065b 163 void CellularConnectionFSM::set_plmn(const char *plmn)
kadonotakashi 0:8fdf9a60065b 164 {
kadonotakashi 0:8fdf9a60065b 165 _plmn = plmn;
kadonotakashi 0:8fdf9a60065b 166 }
kadonotakashi 0:8fdf9a60065b 167
kadonotakashi 0:8fdf9a60065b 168 bool CellularConnectionFSM::open_sim()
kadonotakashi 0:8fdf9a60065b 169 {
kadonotakashi 0:8fdf9a60065b 170 CellularSIM::SimState state = CellularSIM::SimStateUnknown;
kadonotakashi 0:8fdf9a60065b 171 // wait until SIM is readable
kadonotakashi 0:8fdf9a60065b 172 // here you could add wait(secs) if you know start delay of your SIM
kadonotakashi 0:8fdf9a60065b 173 if (_sim->get_sim_state(state) != NSAPI_ERROR_OK) {
kadonotakashi 0:8fdf9a60065b 174 tr_info("Waiting for SIM (err while reading)...");
kadonotakashi 0:8fdf9a60065b 175 if (_event_status_cb) {
kadonotakashi 0:8fdf9a60065b 176 _event_status_cb((nsapi_event_t)CellularSIMStatusChanged, state);
kadonotakashi 0:8fdf9a60065b 177 }
kadonotakashi 0:8fdf9a60065b 178 return false;
kadonotakashi 0:8fdf9a60065b 179 }
kadonotakashi 0:8fdf9a60065b 180
kadonotakashi 0:8fdf9a60065b 181 // report current state so callback can set sim pin if needed
kadonotakashi 0:8fdf9a60065b 182 if (_event_status_cb) {
kadonotakashi 0:8fdf9a60065b 183 _event_status_cb((nsapi_event_t)CellularSIMStatusChanged, state);
kadonotakashi 0:8fdf9a60065b 184 }
kadonotakashi 0:8fdf9a60065b 185
kadonotakashi 0:8fdf9a60065b 186 if (state == CellularSIM::SimStatePinNeeded) {
kadonotakashi 0:8fdf9a60065b 187 if (strlen(_sim_pin)) {
kadonotakashi 0:8fdf9a60065b 188 tr_info("SIM pin required, entering pin");
kadonotakashi 0:8fdf9a60065b 189 nsapi_error_t err = _sim->set_pin(_sim_pin);
kadonotakashi 0:8fdf9a60065b 190 if (err) {
kadonotakashi 0:8fdf9a60065b 191 tr_error("SIM pin set failed with: %d, bailing out...", err);
kadonotakashi 0:8fdf9a60065b 192 }
kadonotakashi 0:8fdf9a60065b 193 } else {
kadonotakashi 0:8fdf9a60065b 194 // No sim pin provided even it's needed, stop state machine
kadonotakashi 0:8fdf9a60065b 195 tr_error("PIN required but No SIM pin provided.");
kadonotakashi 0:8fdf9a60065b 196 _retry_count = MAX_RETRY_ARRAY_SIZE;
kadonotakashi 0:8fdf9a60065b 197 return false;
kadonotakashi 0:8fdf9a60065b 198 }
kadonotakashi 0:8fdf9a60065b 199 }
kadonotakashi 0:8fdf9a60065b 200
kadonotakashi 0:8fdf9a60065b 201 return state == CellularSIM::SimStateReady;
kadonotakashi 0:8fdf9a60065b 202 }
kadonotakashi 0:8fdf9a60065b 203
kadonotakashi 0:8fdf9a60065b 204 bool CellularConnectionFSM::is_registered()
kadonotakashi 0:8fdf9a60065b 205 {
kadonotakashi 0:8fdf9a60065b 206 CellularNetwork::RegistrationStatus status;
kadonotakashi 0:8fdf9a60065b 207 bool is_registered = false;
kadonotakashi 0:8fdf9a60065b 208
kadonotakashi 0:8fdf9a60065b 209 for (int type = 0; type < CellularNetwork::C_MAX; type++) {
kadonotakashi 0:8fdf9a60065b 210 if (get_network_registration((CellularNetwork::RegistrationType) type, status, is_registered)) {
kadonotakashi 0:8fdf9a60065b 211 tr_debug("get_network_registration: type=%d, status=%d", type, status);
kadonotakashi 0:8fdf9a60065b 212 if (is_registered) {
kadonotakashi 0:8fdf9a60065b 213 break;
kadonotakashi 0:8fdf9a60065b 214 }
kadonotakashi 0:8fdf9a60065b 215 }
kadonotakashi 0:8fdf9a60065b 216 }
kadonotakashi 0:8fdf9a60065b 217
kadonotakashi 0:8fdf9a60065b 218 return is_registered;
kadonotakashi 0:8fdf9a60065b 219 }
kadonotakashi 0:8fdf9a60065b 220
kadonotakashi 0:8fdf9a60065b 221 bool CellularConnectionFSM::get_network_registration(CellularNetwork::RegistrationType type,
kadonotakashi 0:8fdf9a60065b 222 CellularNetwork::RegistrationStatus &status, bool &is_registered)
kadonotakashi 0:8fdf9a60065b 223 {
kadonotakashi 0:8fdf9a60065b 224 is_registered = false;
kadonotakashi 0:8fdf9a60065b 225 bool is_roaming = false;
kadonotakashi 0:8fdf9a60065b 226 nsapi_error_t err = _network->get_registration_status(type, status);
kadonotakashi 0:8fdf9a60065b 227 if (err != NSAPI_ERROR_OK) {
kadonotakashi 0:8fdf9a60065b 228 if (err != NSAPI_ERROR_UNSUPPORTED) {
kadonotakashi 0:8fdf9a60065b 229 tr_warn("Get network registration failed (type %d)!", type);
kadonotakashi 0:8fdf9a60065b 230 }
kadonotakashi 0:8fdf9a60065b 231 return false;
kadonotakashi 0:8fdf9a60065b 232 }
kadonotakashi 0:8fdf9a60065b 233 switch (status) {
kadonotakashi 0:8fdf9a60065b 234 case CellularNetwork::RegisteredRoaming:
kadonotakashi 0:8fdf9a60065b 235 is_roaming = true;
kadonotakashi 0:8fdf9a60065b 236 // fall-through
kadonotakashi 0:8fdf9a60065b 237 case CellularNetwork::RegisteredHomeNetwork:
kadonotakashi 0:8fdf9a60065b 238 is_registered = true;
kadonotakashi 0:8fdf9a60065b 239 break;
kadonotakashi 0:8fdf9a60065b 240 case CellularNetwork::RegisteredSMSOnlyRoaming:
kadonotakashi 0:8fdf9a60065b 241 is_roaming = true;
kadonotakashi 0:8fdf9a60065b 242 // fall-through
kadonotakashi 0:8fdf9a60065b 243 case CellularNetwork::RegisteredSMSOnlyHome:
kadonotakashi 0:8fdf9a60065b 244 tr_warn("SMS only network registration!");
kadonotakashi 0:8fdf9a60065b 245 break;
kadonotakashi 0:8fdf9a60065b 246 case CellularNetwork::RegisteredCSFBNotPreferredRoaming:
kadonotakashi 0:8fdf9a60065b 247 is_roaming = true;
kadonotakashi 0:8fdf9a60065b 248 // fall-through
kadonotakashi 0:8fdf9a60065b 249 case CellularNetwork::RegisteredCSFBNotPreferredHome:
kadonotakashi 0:8fdf9a60065b 250 tr_warn("Not preferred network registration!");
kadonotakashi 0:8fdf9a60065b 251 break;
kadonotakashi 0:8fdf9a60065b 252 case CellularNetwork::AttachedEmergencyOnly:
kadonotakashi 0:8fdf9a60065b 253 tr_warn("Emergency only network registration!");
kadonotakashi 0:8fdf9a60065b 254 break;
kadonotakashi 0:8fdf9a60065b 255 case CellularNetwork::RegistrationDenied:
kadonotakashi 0:8fdf9a60065b 256 case CellularNetwork::NotRegistered:
kadonotakashi 0:8fdf9a60065b 257 case CellularNetwork::Unknown:
kadonotakashi 0:8fdf9a60065b 258 case CellularNetwork::SearchingNetwork:
kadonotakashi 0:8fdf9a60065b 259 default:
kadonotakashi 0:8fdf9a60065b 260 break;
kadonotakashi 0:8fdf9a60065b 261 }
kadonotakashi 0:8fdf9a60065b 262
kadonotakashi 0:8fdf9a60065b 263 if (is_roaming) {
kadonotakashi 0:8fdf9a60065b 264 tr_warn("Roaming cellular network!");
kadonotakashi 0:8fdf9a60065b 265 }
kadonotakashi 0:8fdf9a60065b 266
kadonotakashi 0:8fdf9a60065b 267 return true;
kadonotakashi 0:8fdf9a60065b 268 }
kadonotakashi 0:8fdf9a60065b 269
kadonotakashi 0:8fdf9a60065b 270 void CellularConnectionFSM::report_failure(const char *msg)
kadonotakashi 0:8fdf9a60065b 271 {
kadonotakashi 0:8fdf9a60065b 272 tr_error("Cellular network failed: %s", msg);
kadonotakashi 0:8fdf9a60065b 273 if (_status_callback) {
kadonotakashi 0:8fdf9a60065b 274 _status_callback(_state, _next_state);
kadonotakashi 0:8fdf9a60065b 275 }
kadonotakashi 0:8fdf9a60065b 276 }
kadonotakashi 0:8fdf9a60065b 277
kadonotakashi 0:8fdf9a60065b 278 const char *CellularConnectionFSM::get_state_string(CellularState state)
kadonotakashi 0:8fdf9a60065b 279 {
kadonotakashi 0:8fdf9a60065b 280 #if MBED_CONF_MBED_TRACE_ENABLE
kadonotakashi 0:8fdf9a60065b 281 static const char *strings[] = { "Init", "Power", "Device ready", "SIM pin", "Registering network", "Manual registering", "Attaching network", "Activating PDP Context", "Connecting network", "Connected"};
kadonotakashi 0:8fdf9a60065b 282 return strings[state];
kadonotakashi 0:8fdf9a60065b 283 #else
kadonotakashi 0:8fdf9a60065b 284 return NULL;
kadonotakashi 0:8fdf9a60065b 285 #endif // #if MBED_CONF_MBED_TRACE_ENABLE
kadonotakashi 0:8fdf9a60065b 286 }
kadonotakashi 0:8fdf9a60065b 287
kadonotakashi 0:8fdf9a60065b 288 bool CellularConnectionFSM::is_registered_to_plmn()
kadonotakashi 0:8fdf9a60065b 289 {
kadonotakashi 0:8fdf9a60065b 290 int format;
kadonotakashi 0:8fdf9a60065b 291 CellularNetwork::operator_t op;
kadonotakashi 0:8fdf9a60065b 292
kadonotakashi 0:8fdf9a60065b 293 nsapi_error_t err = _network->get_operator_params(format, op);
kadonotakashi 0:8fdf9a60065b 294 if (err == NSAPI_ERROR_OK) {
kadonotakashi 0:8fdf9a60065b 295 if (format == 2) {
kadonotakashi 0:8fdf9a60065b 296 // great, numeric format we can do comparison for that
kadonotakashi 0:8fdf9a60065b 297 if (strcmp(op.op_num, _plmn) == 0) {
kadonotakashi 0:8fdf9a60065b 298 return true;
kadonotakashi 0:8fdf9a60065b 299 }
kadonotakashi 0:8fdf9a60065b 300 return false;
kadonotakashi 0:8fdf9a60065b 301 }
kadonotakashi 0:8fdf9a60065b 302
kadonotakashi 0:8fdf9a60065b 303 // format was alpha, get operator names to do the comparing
kadonotakashi 0:8fdf9a60065b 304 CellularNetwork::operator_names_list names_list;
kadonotakashi 0:8fdf9a60065b 305 nsapi_error_t err = _network->get_operator_names(names_list);
kadonotakashi 0:8fdf9a60065b 306 if (err == NSAPI_ERROR_OK) {
kadonotakashi 0:8fdf9a60065b 307 CellularNetwork::operator_names_t *op_names = names_list.get_head();
kadonotakashi 0:8fdf9a60065b 308 bool found_match = false;
kadonotakashi 0:8fdf9a60065b 309 while (op_names) {
kadonotakashi 0:8fdf9a60065b 310 if (format == 0) {
kadonotakashi 0:8fdf9a60065b 311 if (strcmp(op.op_long, op_names->alpha) == 0) {
kadonotakashi 0:8fdf9a60065b 312 found_match = true;
kadonotakashi 0:8fdf9a60065b 313 }
kadonotakashi 0:8fdf9a60065b 314 } else if (format == 1) {
kadonotakashi 0:8fdf9a60065b 315 if (strcmp(op.op_short, op_names->alpha) == 0) {
kadonotakashi 0:8fdf9a60065b 316 found_match = true;
kadonotakashi 0:8fdf9a60065b 317 }
kadonotakashi 0:8fdf9a60065b 318 }
kadonotakashi 0:8fdf9a60065b 319
kadonotakashi 0:8fdf9a60065b 320 if (found_match) {
kadonotakashi 0:8fdf9a60065b 321 if (strcmp(_plmn, op_names->numeric)) {
kadonotakashi 0:8fdf9a60065b 322 names_list.delete_all();
kadonotakashi 0:8fdf9a60065b 323 return true;
kadonotakashi 0:8fdf9a60065b 324 }
kadonotakashi 0:8fdf9a60065b 325 names_list.delete_all();
kadonotakashi 0:8fdf9a60065b 326 return false;
kadonotakashi 0:8fdf9a60065b 327 }
kadonotakashi 0:8fdf9a60065b 328 }
kadonotakashi 0:8fdf9a60065b 329 }
kadonotakashi 0:8fdf9a60065b 330 names_list.delete_all();
kadonotakashi 0:8fdf9a60065b 331 }
kadonotakashi 0:8fdf9a60065b 332
kadonotakashi 0:8fdf9a60065b 333 return false;
kadonotakashi 0:8fdf9a60065b 334 }
kadonotakashi 0:8fdf9a60065b 335
kadonotakashi 0:8fdf9a60065b 336 nsapi_error_t CellularConnectionFSM::continue_from_state(CellularState state)
kadonotakashi 0:8fdf9a60065b 337 {
kadonotakashi 0:8fdf9a60065b 338 tr_info("Continue state from %s to %s", get_state_string((CellularConnectionFSM::CellularState)_state),
kadonotakashi 0:8fdf9a60065b 339 get_state_string((CellularConnectionFSM::CellularState)state));
kadonotakashi 0:8fdf9a60065b 340 _state = state;
kadonotakashi 0:8fdf9a60065b 341 _next_state = state;
kadonotakashi 0:8fdf9a60065b 342 _retry_count = 0;
kadonotakashi 0:8fdf9a60065b 343 if (!_queue.call_in(0, callback(this, &CellularConnectionFSM::event))) {
kadonotakashi 0:8fdf9a60065b 344 stop();
kadonotakashi 0:8fdf9a60065b 345 return NSAPI_ERROR_NO_MEMORY;
kadonotakashi 0:8fdf9a60065b 346 }
kadonotakashi 0:8fdf9a60065b 347
kadonotakashi 0:8fdf9a60065b 348 return NSAPI_ERROR_OK;
kadonotakashi 0:8fdf9a60065b 349 }
kadonotakashi 0:8fdf9a60065b 350
kadonotakashi 0:8fdf9a60065b 351 nsapi_error_t CellularConnectionFSM::continue_to_state(CellularState state)
kadonotakashi 0:8fdf9a60065b 352 {
kadonotakashi 0:8fdf9a60065b 353 MBED_ASSERT(_cellularDevice);
kadonotakashi 0:8fdf9a60065b 354 _retry_count = 0;
kadonotakashi 0:8fdf9a60065b 355 if (state < _state) {
kadonotakashi 0:8fdf9a60065b 356 _state = state;
kadonotakashi 0:8fdf9a60065b 357 } else {
kadonotakashi 0:8fdf9a60065b 358 // update next state so that we don't continue from previous state
kadonotakashi 0:8fdf9a60065b 359 _state = _next_state;
kadonotakashi 0:8fdf9a60065b 360 }
kadonotakashi 0:8fdf9a60065b 361 if (!_queue.call_in(0, callback(this, &CellularConnectionFSM::event))) {
kadonotakashi 0:8fdf9a60065b 362 stop();
kadonotakashi 0:8fdf9a60065b 363 return NSAPI_ERROR_NO_MEMORY;
kadonotakashi 0:8fdf9a60065b 364 }
kadonotakashi 0:8fdf9a60065b 365
kadonotakashi 0:8fdf9a60065b 366 return NSAPI_ERROR_OK;
kadonotakashi 0:8fdf9a60065b 367 }
kadonotakashi 0:8fdf9a60065b 368
kadonotakashi 0:8fdf9a60065b 369 void CellularConnectionFSM::enter_to_state(CellularState state)
kadonotakashi 0:8fdf9a60065b 370 {
kadonotakashi 0:8fdf9a60065b 371 _next_state = state;
kadonotakashi 0:8fdf9a60065b 372 _retry_count = 0;
kadonotakashi 0:8fdf9a60065b 373 _command_success = false;
kadonotakashi 0:8fdf9a60065b 374 }
kadonotakashi 0:8fdf9a60065b 375
kadonotakashi 0:8fdf9a60065b 376 void CellularConnectionFSM::retry_state_or_fail()
kadonotakashi 0:8fdf9a60065b 377 {
kadonotakashi 0:8fdf9a60065b 378 if (++_retry_count < MAX_RETRY_ARRAY_SIZE) {
kadonotakashi 0:8fdf9a60065b 379 tr_debug("Retry State %s, retry %d/%d", get_state_string(_state), _retry_count, MAX_RETRY_ARRAY_SIZE);
kadonotakashi 0:8fdf9a60065b 380 _event_timeout = _retry_timeout_array[_retry_count];
kadonotakashi 0:8fdf9a60065b 381 } else {
kadonotakashi 0:8fdf9a60065b 382 report_failure(get_state_string(_state));
kadonotakashi 0:8fdf9a60065b 383 return;
kadonotakashi 0:8fdf9a60065b 384 }
kadonotakashi 0:8fdf9a60065b 385 }
kadonotakashi 0:8fdf9a60065b 386
kadonotakashi 0:8fdf9a60065b 387 void CellularConnectionFSM::state_init()
kadonotakashi 0:8fdf9a60065b 388 {
kadonotakashi 0:8fdf9a60065b 389 // we should check that if power is already on then we can jump to device ready state
kadonotakashi 0:8fdf9a60065b 390 _cellularDevice->set_timeout(TIMEOUT_POWER_ON);
kadonotakashi 0:8fdf9a60065b 391 tr_info("Cellular state init (timeout %d ms)", TIMEOUT_POWER_ON);
kadonotakashi 0:8fdf9a60065b 392 nsapi_error_t err = _power->is_device_ready();
kadonotakashi 0:8fdf9a60065b 393 if (err != NSAPI_ERROR_OK) {
kadonotakashi 0:8fdf9a60065b 394 _event_timeout = _start_time;
kadonotakashi 0:8fdf9a60065b 395 tr_info("Init state, waiting %d ms before POWER state)", _start_time);
kadonotakashi 0:8fdf9a60065b 396 enter_to_state(STATE_POWER_ON);
kadonotakashi 0:8fdf9a60065b 397 } else {
kadonotakashi 0:8fdf9a60065b 398 tr_info("Device was ready to accept commands, jump to device ready");
kadonotakashi 0:8fdf9a60065b 399 enter_to_state(STATE_DEVICE_READY);
kadonotakashi 0:8fdf9a60065b 400 }
kadonotakashi 0:8fdf9a60065b 401 }
kadonotakashi 0:8fdf9a60065b 402
kadonotakashi 0:8fdf9a60065b 403 void CellularConnectionFSM::state_power_on()
kadonotakashi 0:8fdf9a60065b 404 {
kadonotakashi 0:8fdf9a60065b 405 _cellularDevice->set_timeout(TIMEOUT_POWER_ON);
kadonotakashi 0:8fdf9a60065b 406 tr_info("Cellular power ON (timeout %d ms)", TIMEOUT_POWER_ON);
kadonotakashi 0:8fdf9a60065b 407 if (power_on()) {
kadonotakashi 0:8fdf9a60065b 408 enter_to_state(STATE_DEVICE_READY);
kadonotakashi 0:8fdf9a60065b 409 } else {
kadonotakashi 0:8fdf9a60065b 410 // retry to power on device
kadonotakashi 0:8fdf9a60065b 411 retry_state_or_fail();
kadonotakashi 0:8fdf9a60065b 412 }
kadonotakashi 0:8fdf9a60065b 413 }
kadonotakashi 0:8fdf9a60065b 414
kadonotakashi 0:8fdf9a60065b 415 bool CellularConnectionFSM::device_ready()
kadonotakashi 0:8fdf9a60065b 416 {
kadonotakashi 0:8fdf9a60065b 417 if (_cellularDevice->init_module(_serial) != NSAPI_ERROR_OK) {
kadonotakashi 0:8fdf9a60065b 418 return false;
kadonotakashi 0:8fdf9a60065b 419 }
kadonotakashi 0:8fdf9a60065b 420 tr_info("Cellular device ready");
kadonotakashi 0:8fdf9a60065b 421 if (_event_status_cb) {
kadonotakashi 0:8fdf9a60065b 422 _event_status_cb((nsapi_event_t)CellularDeviceReady, 0);
kadonotakashi 0:8fdf9a60065b 423 }
kadonotakashi 0:8fdf9a60065b 424 _power->remove_device_ready_urc_cb(mbed::callback(this, &CellularConnectionFSM::ready_urc_cb));
kadonotakashi 0:8fdf9a60065b 425 _cellularDevice->close_power();
kadonotakashi 0:8fdf9a60065b 426 _power = NULL;
kadonotakashi 0:8fdf9a60065b 427 return true;
kadonotakashi 0:8fdf9a60065b 428 }
kadonotakashi 0:8fdf9a60065b 429
kadonotakashi 0:8fdf9a60065b 430 void CellularConnectionFSM::state_device_ready()
kadonotakashi 0:8fdf9a60065b 431 {
kadonotakashi 0:8fdf9a60065b 432 _cellularDevice->set_timeout(TIMEOUT_POWER_ON);
kadonotakashi 0:8fdf9a60065b 433 if (_power->set_at_mode() == NSAPI_ERROR_OK) {
kadonotakashi 0:8fdf9a60065b 434 if (device_ready()) {
kadonotakashi 0:8fdf9a60065b 435 enter_to_state(STATE_SIM_PIN);
kadonotakashi 0:8fdf9a60065b 436 }
kadonotakashi 0:8fdf9a60065b 437 } else {
kadonotakashi 0:8fdf9a60065b 438 if (_retry_count == 0) {
kadonotakashi 0:8fdf9a60065b 439 (void)_power->set_device_ready_urc_cb(mbed::callback(this, &CellularConnectionFSM::ready_urc_cb));
kadonotakashi 0:8fdf9a60065b 440 }
kadonotakashi 0:8fdf9a60065b 441 retry_state_or_fail();
kadonotakashi 0:8fdf9a60065b 442 }
kadonotakashi 0:8fdf9a60065b 443 }
kadonotakashi 0:8fdf9a60065b 444
kadonotakashi 0:8fdf9a60065b 445 void CellularConnectionFSM::state_sim_pin()
kadonotakashi 0:8fdf9a60065b 446 {
kadonotakashi 0:8fdf9a60065b 447 _cellularDevice->set_timeout(TIMEOUT_SIM_PIN);
kadonotakashi 0:8fdf9a60065b 448 tr_info("Sim state (timeout %d ms)", TIMEOUT_SIM_PIN);
kadonotakashi 0:8fdf9a60065b 449 if (open_sim()) {
kadonotakashi 0:8fdf9a60065b 450 bool success = false;
kadonotakashi 0:8fdf9a60065b 451 for (int type = 0; type < CellularNetwork::C_MAX; type++) {
kadonotakashi 0:8fdf9a60065b 452 if (!_network->set_registration_urc((CellularNetwork::RegistrationType)type, true)) {
kadonotakashi 0:8fdf9a60065b 453 success = true;
kadonotakashi 0:8fdf9a60065b 454 }
kadonotakashi 0:8fdf9a60065b 455 }
kadonotakashi 0:8fdf9a60065b 456 if (!success) {
kadonotakashi 0:8fdf9a60065b 457 tr_warn("Failed to set any URC's for registration");
kadonotakashi 0:8fdf9a60065b 458 retry_state_or_fail();
kadonotakashi 0:8fdf9a60065b 459 return;
kadonotakashi 0:8fdf9a60065b 460 }
kadonotakashi 0:8fdf9a60065b 461 if (_plmn) {
kadonotakashi 0:8fdf9a60065b 462 enter_to_state(STATE_MANUAL_REGISTERING_NETWORK);
kadonotakashi 0:8fdf9a60065b 463 } else {
kadonotakashi 0:8fdf9a60065b 464 enter_to_state(STATE_REGISTERING_NETWORK);
kadonotakashi 0:8fdf9a60065b 465 }
kadonotakashi 0:8fdf9a60065b 466 } else {
kadonotakashi 0:8fdf9a60065b 467 retry_state_or_fail();
kadonotakashi 0:8fdf9a60065b 468 }
kadonotakashi 0:8fdf9a60065b 469 }
kadonotakashi 0:8fdf9a60065b 470
kadonotakashi 0:8fdf9a60065b 471 void CellularConnectionFSM::state_registering()
kadonotakashi 0:8fdf9a60065b 472 {
kadonotakashi 0:8fdf9a60065b 473 _cellularDevice->set_timeout(TIMEOUT_NETWORK);
kadonotakashi 0:8fdf9a60065b 474 if (is_registered()) {
kadonotakashi 0:8fdf9a60065b 475 // we are already registered, go to attach
kadonotakashi 0:8fdf9a60065b 476 enter_to_state(STATE_ATTACHING_NETWORK);
kadonotakashi 0:8fdf9a60065b 477 } else {
kadonotakashi 0:8fdf9a60065b 478 _cellularDevice->set_timeout(TIMEOUT_REGISTRATION);
kadonotakashi 0:8fdf9a60065b 479 if (!_command_success) {
kadonotakashi 0:8fdf9a60065b 480 _command_success = (_network->set_registration() == NSAPI_ERROR_OK);
kadonotakashi 0:8fdf9a60065b 481 }
kadonotakashi 0:8fdf9a60065b 482 retry_state_or_fail();
kadonotakashi 0:8fdf9a60065b 483 }
kadonotakashi 0:8fdf9a60065b 484 }
kadonotakashi 0:8fdf9a60065b 485
kadonotakashi 0:8fdf9a60065b 486 // only used when _plmn is set
kadonotakashi 0:8fdf9a60065b 487 void CellularConnectionFSM::state_manual_registering_network()
kadonotakashi 0:8fdf9a60065b 488 {
kadonotakashi 0:8fdf9a60065b 489 _cellularDevice->set_timeout(TIMEOUT_REGISTRATION);
kadonotakashi 0:8fdf9a60065b 490 tr_info("state_manual_registering_network");
kadonotakashi 0:8fdf9a60065b 491 if (!_plmn_network_found) {
kadonotakashi 0:8fdf9a60065b 492 if (is_registered() && is_registered_to_plmn()) {
kadonotakashi 0:8fdf9a60065b 493 _plmn_network_found = true;
kadonotakashi 0:8fdf9a60065b 494 enter_to_state(STATE_ATTACHING_NETWORK);
kadonotakashi 0:8fdf9a60065b 495 } else {
kadonotakashi 0:8fdf9a60065b 496 if (!_command_success) {
kadonotakashi 0:8fdf9a60065b 497 _command_success = (_network->set_registration(_plmn) == NSAPI_ERROR_OK);
kadonotakashi 0:8fdf9a60065b 498 }
kadonotakashi 0:8fdf9a60065b 499 retry_state_or_fail();
kadonotakashi 0:8fdf9a60065b 500 }
kadonotakashi 0:8fdf9a60065b 501 }
kadonotakashi 0:8fdf9a60065b 502 }
kadonotakashi 0:8fdf9a60065b 503
kadonotakashi 0:8fdf9a60065b 504 void CellularConnectionFSM::state_attaching()
kadonotakashi 0:8fdf9a60065b 505 {
kadonotakashi 0:8fdf9a60065b 506 _cellularDevice->set_timeout(TIMEOUT_CONNECT);
kadonotakashi 0:8fdf9a60065b 507 if (_network->set_attach() == NSAPI_ERROR_OK) {
kadonotakashi 0:8fdf9a60065b 508 _cellularDevice->close_sim();
kadonotakashi 0:8fdf9a60065b 509 _sim = NULL;
kadonotakashi 0:8fdf9a60065b 510 enter_to_state(STATE_ACTIVATING_PDP_CONTEXT);
kadonotakashi 0:8fdf9a60065b 511 } else {
kadonotakashi 0:8fdf9a60065b 512 retry_state_or_fail();
kadonotakashi 0:8fdf9a60065b 513 }
kadonotakashi 0:8fdf9a60065b 514 }
kadonotakashi 0:8fdf9a60065b 515
kadonotakashi 0:8fdf9a60065b 516 void CellularConnectionFSM::state_activating_pdp_context()
kadonotakashi 0:8fdf9a60065b 517 {
kadonotakashi 0:8fdf9a60065b 518 _cellularDevice->set_timeout(TIMEOUT_CONNECT);
kadonotakashi 0:8fdf9a60065b 519 tr_info("Activate PDP Context (timeout %d ms)", TIMEOUT_CONNECT);
kadonotakashi 0:8fdf9a60065b 520 if (_network->activate_context() == NSAPI_ERROR_OK) {
kadonotakashi 0:8fdf9a60065b 521 // when using modems stack connect is synchronous
kadonotakashi 0:8fdf9a60065b 522 _next_state = STATE_CONNECTING_NETWORK;
kadonotakashi 0:8fdf9a60065b 523 } else {
kadonotakashi 0:8fdf9a60065b 524 retry_state_or_fail();
kadonotakashi 0:8fdf9a60065b 525 }
kadonotakashi 0:8fdf9a60065b 526 }
kadonotakashi 0:8fdf9a60065b 527
kadonotakashi 0:8fdf9a60065b 528 void CellularConnectionFSM::state_connect_to_network()
kadonotakashi 0:8fdf9a60065b 529 {
kadonotakashi 0:8fdf9a60065b 530 _cellularDevice->set_timeout(TIMEOUT_CONNECT);
kadonotakashi 0:8fdf9a60065b 531 tr_info("Connect to cellular network (timeout %d ms)", TIMEOUT_CONNECT);
kadonotakashi 0:8fdf9a60065b 532 if (_network->connect() == NSAPI_ERROR_OK) {
kadonotakashi 0:8fdf9a60065b 533 _cellularDevice->set_timeout(TIMEOUT_NETWORK);
kadonotakashi 0:8fdf9a60065b 534 tr_debug("Connected to cellular network, set at timeout (timeout %d ms)", TIMEOUT_NETWORK);
kadonotakashi 0:8fdf9a60065b 535 // when using modems stack connect is synchronous
kadonotakashi 0:8fdf9a60065b 536 _next_state = STATE_CONNECTED;
kadonotakashi 0:8fdf9a60065b 537 } else {
kadonotakashi 0:8fdf9a60065b 538 retry_state_or_fail();
kadonotakashi 0:8fdf9a60065b 539 }
kadonotakashi 0:8fdf9a60065b 540 }
kadonotakashi 0:8fdf9a60065b 541
kadonotakashi 0:8fdf9a60065b 542 void CellularConnectionFSM::state_connected()
kadonotakashi 0:8fdf9a60065b 543 {
kadonotakashi 0:8fdf9a60065b 544 _cellularDevice->set_timeout(TIMEOUT_NETWORK);
kadonotakashi 0:8fdf9a60065b 545 tr_debug("Cellular ready! (timeout %d ms)", TIMEOUT_NETWORK);
kadonotakashi 0:8fdf9a60065b 546 if (_status_callback) {
kadonotakashi 0:8fdf9a60065b 547 _status_callback(_state, _next_state);
kadonotakashi 0:8fdf9a60065b 548 }
kadonotakashi 0:8fdf9a60065b 549 }
kadonotakashi 0:8fdf9a60065b 550
kadonotakashi 0:8fdf9a60065b 551 void CellularConnectionFSM::event()
kadonotakashi 0:8fdf9a60065b 552 {
kadonotakashi 0:8fdf9a60065b 553 _event_timeout = -1;
kadonotakashi 0:8fdf9a60065b 554 switch (_state) {
kadonotakashi 0:8fdf9a60065b 555 case STATE_INIT:
kadonotakashi 0:8fdf9a60065b 556 state_init();
kadonotakashi 0:8fdf9a60065b 557 break;
kadonotakashi 0:8fdf9a60065b 558 case STATE_POWER_ON:
kadonotakashi 0:8fdf9a60065b 559 state_power_on();
kadonotakashi 0:8fdf9a60065b 560 break;
kadonotakashi 0:8fdf9a60065b 561 case STATE_DEVICE_READY:
kadonotakashi 0:8fdf9a60065b 562 state_device_ready();
kadonotakashi 0:8fdf9a60065b 563 break;
kadonotakashi 0:8fdf9a60065b 564 case STATE_SIM_PIN:
kadonotakashi 0:8fdf9a60065b 565 state_sim_pin();
kadonotakashi 0:8fdf9a60065b 566 break;
kadonotakashi 0:8fdf9a60065b 567 case STATE_REGISTERING_NETWORK:
kadonotakashi 0:8fdf9a60065b 568 state_registering();
kadonotakashi 0:8fdf9a60065b 569 break;
kadonotakashi 0:8fdf9a60065b 570 case STATE_MANUAL_REGISTERING_NETWORK:
kadonotakashi 0:8fdf9a60065b 571 state_manual_registering_network();
kadonotakashi 0:8fdf9a60065b 572 break;
kadonotakashi 0:8fdf9a60065b 573 case STATE_ATTACHING_NETWORK:
kadonotakashi 0:8fdf9a60065b 574 state_attaching();
kadonotakashi 0:8fdf9a60065b 575 break;
kadonotakashi 0:8fdf9a60065b 576 case STATE_ACTIVATING_PDP_CONTEXT:
kadonotakashi 0:8fdf9a60065b 577 state_activating_pdp_context();
kadonotakashi 0:8fdf9a60065b 578 break;
kadonotakashi 0:8fdf9a60065b 579 case STATE_CONNECTING_NETWORK:
kadonotakashi 0:8fdf9a60065b 580 state_connect_to_network();
kadonotakashi 0:8fdf9a60065b 581 break;
kadonotakashi 0:8fdf9a60065b 582 case STATE_CONNECTED:
kadonotakashi 0:8fdf9a60065b 583 state_connected();
kadonotakashi 0:8fdf9a60065b 584 break;
kadonotakashi 0:8fdf9a60065b 585 default:
kadonotakashi 0:8fdf9a60065b 586 MBED_ASSERT(0);
kadonotakashi 0:8fdf9a60065b 587 break;
kadonotakashi 0:8fdf9a60065b 588 }
kadonotakashi 0:8fdf9a60065b 589
kadonotakashi 0:8fdf9a60065b 590 if (_next_state != _state || _event_timeout >= 0) {
kadonotakashi 0:8fdf9a60065b 591 if (_next_state != _state) { // state exit condition
kadonotakashi 0:8fdf9a60065b 592 tr_info("Cellular state from %s to %s", get_state_string((CellularConnectionFSM::CellularState)_state),
kadonotakashi 0:8fdf9a60065b 593 get_state_string((CellularConnectionFSM::CellularState)_next_state));
kadonotakashi 0:8fdf9a60065b 594 if (_status_callback) {
kadonotakashi 0:8fdf9a60065b 595 if (!_status_callback(_state, _next_state)) {
kadonotakashi 0:8fdf9a60065b 596 return;
kadonotakashi 0:8fdf9a60065b 597 }
kadonotakashi 0:8fdf9a60065b 598 }
kadonotakashi 0:8fdf9a60065b 599 } else {
kadonotakashi 0:8fdf9a60065b 600 tr_info("Cellular event in %d seconds", _event_timeout);
kadonotakashi 0:8fdf9a60065b 601 }
kadonotakashi 0:8fdf9a60065b 602 _state = _next_state;
kadonotakashi 0:8fdf9a60065b 603 if (_event_timeout == -1) {
kadonotakashi 0:8fdf9a60065b 604 _event_timeout = 0;
kadonotakashi 0:8fdf9a60065b 605 }
kadonotakashi 0:8fdf9a60065b 606 _event_id = _queue.call_in(_event_timeout * 1000, callback(this, &CellularConnectionFSM::event));
kadonotakashi 0:8fdf9a60065b 607 if (!_event_id) {
kadonotakashi 0:8fdf9a60065b 608 report_failure("Cellular event failure!");
kadonotakashi 0:8fdf9a60065b 609 return;
kadonotakashi 0:8fdf9a60065b 610 }
kadonotakashi 0:8fdf9a60065b 611 }
kadonotakashi 0:8fdf9a60065b 612 }
kadonotakashi 0:8fdf9a60065b 613
kadonotakashi 0:8fdf9a60065b 614 nsapi_error_t CellularConnectionFSM::start_dispatch()
kadonotakashi 0:8fdf9a60065b 615 {
kadonotakashi 0:8fdf9a60065b 616 MBED_ASSERT(!_queue_thread);
kadonotakashi 0:8fdf9a60065b 617
kadonotakashi 0:8fdf9a60065b 618 _queue_thread = new rtos::Thread(osPriorityNormal, 2048);
kadonotakashi 0:8fdf9a60065b 619 if (!_queue_thread) {
kadonotakashi 0:8fdf9a60065b 620 stop();
kadonotakashi 0:8fdf9a60065b 621 return NSAPI_ERROR_NO_MEMORY;
kadonotakashi 0:8fdf9a60065b 622 }
kadonotakashi 0:8fdf9a60065b 623 if (_queue_thread->start(callback(&_queue, &events::EventQueue::dispatch_forever)) != osOK) {
kadonotakashi 0:8fdf9a60065b 624 stop();
kadonotakashi 0:8fdf9a60065b 625 return NSAPI_ERROR_NO_MEMORY;
kadonotakashi 0:8fdf9a60065b 626 }
kadonotakashi 0:8fdf9a60065b 627
kadonotakashi 0:8fdf9a60065b 628 return NSAPI_ERROR_OK;
kadonotakashi 0:8fdf9a60065b 629 }
kadonotakashi 0:8fdf9a60065b 630
kadonotakashi 0:8fdf9a60065b 631 void CellularConnectionFSM::set_serial(UARTSerial *serial)
kadonotakashi 0:8fdf9a60065b 632 {
kadonotakashi 0:8fdf9a60065b 633 _serial = serial;
kadonotakashi 0:8fdf9a60065b 634 }
kadonotakashi 0:8fdf9a60065b 635
kadonotakashi 0:8fdf9a60065b 636 void CellularConnectionFSM::set_callback(mbed::Callback<bool(int, int)> status_callback)
kadonotakashi 0:8fdf9a60065b 637 {
kadonotakashi 0:8fdf9a60065b 638 _status_callback = status_callback;
kadonotakashi 0:8fdf9a60065b 639 }
kadonotakashi 0:8fdf9a60065b 640
kadonotakashi 0:8fdf9a60065b 641 void CellularConnectionFSM::attach(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb)
kadonotakashi 0:8fdf9a60065b 642 {
kadonotakashi 0:8fdf9a60065b 643 MBED_ASSERT(_network);
kadonotakashi 0:8fdf9a60065b 644 _event_status_cb = status_cb;
kadonotakashi 0:8fdf9a60065b 645 if (status_cb) {
kadonotakashi 0:8fdf9a60065b 646 _network->attach(callback(this, &CellularConnectionFSM::network_callback));
kadonotakashi 0:8fdf9a60065b 647 } else {
kadonotakashi 0:8fdf9a60065b 648 _network->attach(NULL);
kadonotakashi 0:8fdf9a60065b 649 }
kadonotakashi 0:8fdf9a60065b 650 }
kadonotakashi 0:8fdf9a60065b 651
kadonotakashi 0:8fdf9a60065b 652 void CellularConnectionFSM::network_callback(nsapi_event_t ev, intptr_t ptr)
kadonotakashi 0:8fdf9a60065b 653 {
kadonotakashi 0:8fdf9a60065b 654 tr_info("FSM: network_callback called with event: %d, intptr: %d, _state: %s", ev, ptr, get_state_string(_state));
kadonotakashi 0:8fdf9a60065b 655 if ((cellular_connection_status_t)ev == CellularRegistrationStatusChanged &&
kadonotakashi 0:8fdf9a60065b 656 (_state == STATE_REGISTERING_NETWORK || _state == STATE_MANUAL_REGISTERING_NETWORK)) {
kadonotakashi 0:8fdf9a60065b 657 // expect packet data so only these states are valid
kadonotakashi 0:8fdf9a60065b 658 if (ptr == CellularNetwork::RegisteredHomeNetwork || ptr == CellularNetwork::RegisteredRoaming) {
kadonotakashi 0:8fdf9a60065b 659 if (_plmn) {
kadonotakashi 0:8fdf9a60065b 660 if (is_registered_to_plmn()) {
kadonotakashi 0:8fdf9a60065b 661 if (!_plmn_network_found) {
kadonotakashi 0:8fdf9a60065b 662 _plmn_network_found = true;
kadonotakashi 0:8fdf9a60065b 663 _queue.cancel(_event_id);
kadonotakashi 0:8fdf9a60065b 664 continue_from_state(STATE_ATTACHING_NETWORK);
kadonotakashi 0:8fdf9a60065b 665 }
kadonotakashi 0:8fdf9a60065b 666 }
kadonotakashi 0:8fdf9a60065b 667 } else {
kadonotakashi 0:8fdf9a60065b 668 _queue.cancel(_event_id);
kadonotakashi 0:8fdf9a60065b 669 continue_from_state(STATE_ATTACHING_NETWORK);
kadonotakashi 0:8fdf9a60065b 670 }
kadonotakashi 0:8fdf9a60065b 671 }
kadonotakashi 0:8fdf9a60065b 672 }
kadonotakashi 0:8fdf9a60065b 673
kadonotakashi 0:8fdf9a60065b 674 if (_event_status_cb) {
kadonotakashi 0:8fdf9a60065b 675 _event_status_cb(ev, ptr);
kadonotakashi 0:8fdf9a60065b 676 }
kadonotakashi 0:8fdf9a60065b 677 }
kadonotakashi 0:8fdf9a60065b 678
kadonotakashi 0:8fdf9a60065b 679 void CellularConnectionFSM::ready_urc_cb()
kadonotakashi 0:8fdf9a60065b 680 {
kadonotakashi 0:8fdf9a60065b 681 tr_debug("Device ready URC func called");
kadonotakashi 0:8fdf9a60065b 682 if (_state == STATE_DEVICE_READY && _power->set_at_mode() == NSAPI_ERROR_OK) {
kadonotakashi 0:8fdf9a60065b 683 tr_debug("State was STATE_DEVICE_READY and at mode ready, cancel state and move to next");
kadonotakashi 0:8fdf9a60065b 684 if (device_ready()) {
kadonotakashi 0:8fdf9a60065b 685 _queue.cancel(_event_id);
kadonotakashi 0:8fdf9a60065b 686 continue_from_state(STATE_SIM_PIN);
kadonotakashi 0:8fdf9a60065b 687 }
kadonotakashi 0:8fdf9a60065b 688 }
kadonotakashi 0:8fdf9a60065b 689 }
kadonotakashi 0:8fdf9a60065b 690
kadonotakashi 0:8fdf9a60065b 691 events::EventQueue *CellularConnectionFSM::get_queue()
kadonotakashi 0:8fdf9a60065b 692 {
kadonotakashi 0:8fdf9a60065b 693 return &_queue;
kadonotakashi 0:8fdf9a60065b 694 }
kadonotakashi 0:8fdf9a60065b 695
kadonotakashi 0:8fdf9a60065b 696 CellularNetwork *CellularConnectionFSM::get_network()
kadonotakashi 0:8fdf9a60065b 697 {
kadonotakashi 0:8fdf9a60065b 698 return _network;
kadonotakashi 0:8fdf9a60065b 699 }
kadonotakashi 0:8fdf9a60065b 700
kadonotakashi 0:8fdf9a60065b 701 CellularDevice *CellularConnectionFSM::get_device()
kadonotakashi 0:8fdf9a60065b 702 {
kadonotakashi 0:8fdf9a60065b 703 return _cellularDevice;
kadonotakashi 0:8fdf9a60065b 704 }
kadonotakashi 0:8fdf9a60065b 705
kadonotakashi 0:8fdf9a60065b 706 CellularSIM *CellularConnectionFSM::get_sim()
kadonotakashi 0:8fdf9a60065b 707 {
kadonotakashi 0:8fdf9a60065b 708 return _sim;
kadonotakashi 0:8fdf9a60065b 709 }
kadonotakashi 0:8fdf9a60065b 710
kadonotakashi 0:8fdf9a60065b 711 NetworkStack *CellularConnectionFSM::get_stack()
kadonotakashi 0:8fdf9a60065b 712 {
kadonotakashi 0:8fdf9a60065b 713 return _cellularDevice->get_stack();
kadonotakashi 0:8fdf9a60065b 714 }
kadonotakashi 0:8fdf9a60065b 715
kadonotakashi 0:8fdf9a60065b 716 void CellularConnectionFSM::set_retry_timeout_array(uint16_t timeout[], int array_len)
kadonotakashi 0:8fdf9a60065b 717 {
kadonotakashi 0:8fdf9a60065b 718 _retry_array_length = array_len > MAX_RETRY_ARRAY_SIZE ? MAX_RETRY_ARRAY_SIZE : array_len;
kadonotakashi 0:8fdf9a60065b 719
kadonotakashi 0:8fdf9a60065b 720 for (int i = 0; i < _retry_array_length; i++) {
kadonotakashi 0:8fdf9a60065b 721 _retry_timeout_array[i] = timeout[i];
kadonotakashi 0:8fdf9a60065b 722 }
kadonotakashi 0:8fdf9a60065b 723 }
kadonotakashi 0:8fdf9a60065b 724
kadonotakashi 0:8fdf9a60065b 725 } // namespace
kadonotakashi 0:8fdf9a60065b 726
kadonotakashi 0:8fdf9a60065b 727 #endif // CELLULAR_DEVICE