takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers CellularConnectionFSM.cpp Source File

CellularConnectionFSM.cpp

00001 /*
00002  * Copyright (c) 2017, Arm Limited and affiliates.
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License");
00006  * you may not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  *     http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 #include "CellularConnectionFSM.h"
00019 
00020 #ifdef CELLULAR_DEVICE
00021 
00022 #ifndef MBED_TRACE_MAX_LEVEL
00023 #define MBED_TRACE_MAX_LEVEL TRACE_LEVEL_INFO
00024 #endif
00025 #include "CellularLog.h"
00026 #include "CellularCommon.h"
00027 #include "CellularDevice.h"
00028 #include "CellularUtil.h"
00029 
00030 // timeout to wait for AT responses
00031 #define TIMEOUT_POWER_ON     (1*1000)
00032 #define TIMEOUT_SIM_PIN      (1*1000)
00033 #define TIMEOUT_NETWORK      (10*1000)
00034 #define TIMEOUT_CONNECT      (60*1000)
00035 #define TIMEOUT_REGISTRATION (180*1000)
00036 
00037 // maximum time when retrying network register, attach and connect in seconds ( 20minutes )
00038 #define TIMEOUT_NETWORK_MAX (20*60)
00039 
00040 #define RETRY_COUNT_DEFAULT 3
00041 
00042 namespace mbed {
00043 
00044 CellularConnectionFSM::CellularConnectionFSM() :
00045     _serial(0), _state(STATE_INIT), _next_state(_state), _status_callback(0), _event_status_cb(0), _network(0), _power(0), _sim(0),
00046     _queue(8 * EVENTS_EVENT_SIZE), _queue_thread(0), _cellularDevice(0), _retry_count(0), _event_timeout(-1),
00047     _at_queue(0), _event_id(0), _plmn(0), _command_success(false), _plmn_network_found(false)
00048 {
00049     memset(_sim_pin, 0, sizeof(_sim_pin));
00050 #if MBED_CONF_CELLULAR_RANDOM_MAX_START_DELAY == 0
00051     _start_time = 0;
00052 #else
00053     // so that not every device don't start at the exact same time (for example after power outage)
00054     _start_time = rand() % (MBED_CONF_CELLULAR_RANDOM_MAX_START_DELAY);
00055 #endif // MBED_CONF_CELLULAR_RANDOM_MAX_START_DELAY
00056 
00057     // set initial retry values in seconds
00058     _retry_timeout_array[0] = 1; // double time on each retry in order to keep network happy
00059     _retry_timeout_array[1] = 2;
00060     _retry_timeout_array[2] = 4;
00061     _retry_timeout_array[3] = 8;
00062     _retry_timeout_array[4] = 16;
00063     _retry_timeout_array[5] = 32;
00064     _retry_timeout_array[6] = 64;
00065     _retry_timeout_array[7] = 128; // if around two minutes was not enough then let's wait much longer
00066     _retry_timeout_array[8] = 600;
00067     _retry_timeout_array[9] = TIMEOUT_NETWORK_MAX;
00068     _retry_array_length = MAX_RETRY_ARRAY_SIZE;
00069 }
00070 
00071 CellularConnectionFSM::~CellularConnectionFSM()
00072 {
00073     stop();
00074 }
00075 
00076 void CellularConnectionFSM::stop()
00077 {
00078     _queue.cancel(_event_id);
00079     _queue.break_dispatch();
00080 
00081     if (_queue_thread) {
00082         _queue_thread->terminate();
00083         delete _queue_thread;
00084         _queue_thread = NULL;
00085     }
00086 
00087     if (_power) {
00088         _cellularDevice->close_power();
00089         _power = NULL;
00090     }
00091 
00092     if (_network) {
00093         _cellularDevice->close_network();
00094         _network = NULL;
00095     }
00096 
00097     if (_sim) {
00098         _cellularDevice->close_sim();
00099         _sim = NULL;
00100     }
00101 
00102     _state = STATE_INIT;
00103     _next_state = _state;
00104 }
00105 
00106 nsapi_error_t CellularConnectionFSM::init()
00107 {
00108     tr_info("CELLULAR_DEVICE: %s", CELLULAR_STRINGIFY(CELLULAR_DEVICE));
00109     _cellularDevice = CellularDevice::get_default_instance();
00110     if (!_cellularDevice) {
00111         stop();
00112         return NSAPI_ERROR_NO_MEMORY ;
00113     }
00114 
00115     _power = _cellularDevice->open_power(_serial);
00116     if (!_power) {
00117         stop();
00118         return NSAPI_ERROR_NO_MEMORY ;
00119     }
00120 
00121     _network = _cellularDevice->open_network(_serial);
00122     if (!_network) {
00123         stop();
00124         return NSAPI_ERROR_NO_MEMORY ;
00125     }
00126 
00127     _sim = _cellularDevice->open_sim(_serial);
00128     if (!_sim) {
00129         stop();
00130         return NSAPI_ERROR_NO_MEMORY ;
00131     }
00132 
00133     _at_queue = _cellularDevice->get_queue();
00134     _at_queue->chain(&_queue);
00135 
00136     _retry_count = 0;
00137     _state = STATE_INIT;
00138     _next_state = STATE_INIT;
00139 
00140     return _network->init();
00141 }
00142 
00143 bool CellularConnectionFSM::power_on()
00144 {
00145     nsapi_error_t err = _power->on();
00146     if (err != NSAPI_ERROR_OK  && err != NSAPI_ERROR_UNSUPPORTED ) {
00147         tr_warn("Cellular start failed. Power off/on.");
00148         err = _power->off();
00149         if (err != NSAPI_ERROR_OK  && err != NSAPI_ERROR_UNSUPPORTED ) {
00150             tr_error("Cellular power down failing after failed power up attempt!");
00151         }
00152         return false;
00153     }
00154     return true;
00155 }
00156 
00157 void CellularConnectionFSM::set_sim_pin(const char *sim_pin)
00158 {
00159     strncpy(_sim_pin, sim_pin, sizeof(_sim_pin));
00160     _sim_pin[sizeof(_sim_pin) - 1] = '\0';
00161 }
00162 
00163 void CellularConnectionFSM::set_plmn(const char *plmn)
00164 {
00165     _plmn = plmn;
00166 }
00167 
00168 bool CellularConnectionFSM::open_sim()
00169 {
00170     CellularSIM::SimState state = CellularSIM::SimStateUnknown;
00171     // wait until SIM is readable
00172     // here you could add wait(secs) if you know start delay of your SIM
00173     if (_sim->get_sim_state(state) != NSAPI_ERROR_OK ) {
00174         tr_info("Waiting for SIM (err while reading)...");
00175         if (_event_status_cb) {
00176             _event_status_cb((nsapi_event_t)CellularSIMStatusChanged, state);
00177         }
00178         return false;
00179     }
00180 
00181     // report current state so callback can set sim pin if needed
00182     if (_event_status_cb) {
00183         _event_status_cb((nsapi_event_t)CellularSIMStatusChanged, state);
00184     }
00185 
00186     if (state == CellularSIM::SimStatePinNeeded) {
00187         if (strlen(_sim_pin)) {
00188             tr_info("SIM pin required, entering pin");
00189             nsapi_error_t err = _sim->set_pin(_sim_pin);
00190             if (err) {
00191                 tr_error("SIM pin set failed with: %d, bailing out...", err);
00192             }
00193         } else {
00194             // No sim pin provided even it's needed, stop state machine
00195             tr_error("PIN required but No SIM pin provided.");
00196             _retry_count = MAX_RETRY_ARRAY_SIZE;
00197             return false;
00198         }
00199     }
00200 
00201     return state == CellularSIM::SimStateReady;
00202 }
00203 
00204 bool CellularConnectionFSM::is_registered()
00205 {
00206     CellularNetwork::RegistrationStatus status;
00207     bool is_registered = false;
00208 
00209     for (int type = 0; type < CellularNetwork::C_MAX; type++) {
00210         if (get_network_registration((CellularNetwork::RegistrationType) type, status, is_registered)) {
00211             tr_debug("get_network_registration: type=%d, status=%d", type, status);
00212             if (is_registered) {
00213                 break;
00214             }
00215         }
00216     }
00217 
00218     return is_registered;
00219 }
00220 
00221 bool CellularConnectionFSM::get_network_registration(CellularNetwork::RegistrationType type,
00222                                                      CellularNetwork::RegistrationStatus &status, bool &is_registered)
00223 {
00224     is_registered = false;
00225     bool is_roaming = false;
00226     nsapi_error_t err = _network->get_registration_status(type, status);
00227     if (err != NSAPI_ERROR_OK ) {
00228         if (err != NSAPI_ERROR_UNSUPPORTED ) {
00229             tr_warn("Get network registration failed (type %d)!", type);
00230         }
00231         return false;
00232     }
00233     switch (status) {
00234         case CellularNetwork::RegisteredRoaming:
00235             is_roaming = true;
00236         // fall-through
00237         case CellularNetwork::RegisteredHomeNetwork:
00238             is_registered = true;
00239             break;
00240         case CellularNetwork::RegisteredSMSOnlyRoaming:
00241             is_roaming = true;
00242         // fall-through
00243         case CellularNetwork::RegisteredSMSOnlyHome:
00244             tr_warn("SMS only network registration!");
00245             break;
00246         case CellularNetwork::RegisteredCSFBNotPreferredRoaming:
00247             is_roaming = true;
00248         // fall-through
00249         case CellularNetwork::RegisteredCSFBNotPreferredHome:
00250             tr_warn("Not preferred network registration!");
00251             break;
00252         case CellularNetwork::AttachedEmergencyOnly:
00253             tr_warn("Emergency only network registration!");
00254             break;
00255         case CellularNetwork::RegistrationDenied:
00256         case CellularNetwork::NotRegistered:
00257         case CellularNetwork::Unknown:
00258         case CellularNetwork::SearchingNetwork:
00259         default:
00260             break;
00261     }
00262 
00263     if (is_roaming) {
00264         tr_warn("Roaming cellular network!");
00265     }
00266 
00267     return true;
00268 }
00269 
00270 void CellularConnectionFSM::report_failure(const char *msg)
00271 {
00272     tr_error("Cellular network failed: %s", msg);
00273     if (_status_callback) {
00274         _status_callback(_state, _next_state);
00275     }
00276 }
00277 
00278 const char *CellularConnectionFSM::get_state_string(CellularState state)
00279 {
00280 #if MBED_CONF_MBED_TRACE_ENABLE
00281     static const char *strings[] = { "Init", "Power", "Device ready", "SIM pin", "Registering network", "Manual registering", "Attaching network", "Activating PDP Context", "Connecting network", "Connected"};
00282     return strings[state];
00283 #else
00284     return NULL;
00285 #endif // #if MBED_CONF_MBED_TRACE_ENABLE
00286 }
00287 
00288 bool CellularConnectionFSM::is_registered_to_plmn()
00289 {
00290     int format;
00291     CellularNetwork::operator_t op;
00292 
00293     nsapi_error_t err = _network->get_operator_params(format, op);
00294     if (err == NSAPI_ERROR_OK ) {
00295         if (format == 2) {
00296             // great, numeric format we can do comparison for that
00297             if (strcmp(op.op_num, _plmn) == 0) {
00298                 return true;
00299             }
00300             return false;
00301         }
00302 
00303         // format was alpha, get operator names to do the comparing
00304         CellularNetwork::operator_names_list names_list;
00305         nsapi_error_t err = _network->get_operator_names(names_list);
00306         if (err == NSAPI_ERROR_OK ) {
00307             CellularNetwork::operator_names_t *op_names = names_list.get_head();
00308             bool found_match = false;
00309             while (op_names) {
00310                 if (format == 0) {
00311                     if (strcmp(op.op_long, op_names->alpha) == 0) {
00312                         found_match = true;
00313                     }
00314                 } else if (format == 1) {
00315                     if (strcmp(op.op_short, op_names->alpha) == 0) {
00316                         found_match = true;
00317                     }
00318                 }
00319 
00320                 if (found_match) {
00321                     if (strcmp(_plmn, op_names->numeric)) {
00322                         names_list.delete_all();
00323                         return true;
00324                     }
00325                     names_list.delete_all();
00326                     return false;
00327                 }
00328             }
00329         }
00330         names_list.delete_all();
00331     }
00332 
00333     return false;
00334 }
00335 
00336 nsapi_error_t CellularConnectionFSM::continue_from_state(CellularState state)
00337 {
00338     tr_info("Continue state from %s to %s", get_state_string((CellularConnectionFSM::CellularState)_state),
00339             get_state_string((CellularConnectionFSM::CellularState)state));
00340     _state = state;
00341     _next_state = state;
00342     _retry_count = 0;
00343     if (!_queue.call_in(0, callback(this, &CellularConnectionFSM::event))) {
00344         stop();
00345         return NSAPI_ERROR_NO_MEMORY ;
00346     }
00347 
00348     return NSAPI_ERROR_OK ;
00349 }
00350 
00351 nsapi_error_t CellularConnectionFSM::continue_to_state(CellularState state)
00352 {
00353     MBED_ASSERT(_cellularDevice);
00354     _retry_count = 0;
00355     if (state < _state) {
00356         _state = state;
00357     } else {
00358         // update next state so that we don't continue from previous state
00359         _state = _next_state;
00360     }
00361     if (!_queue.call_in(0, callback(this, &CellularConnectionFSM::event))) {
00362         stop();
00363         return NSAPI_ERROR_NO_MEMORY ;
00364     }
00365 
00366     return NSAPI_ERROR_OK ;
00367 }
00368 
00369 void CellularConnectionFSM::enter_to_state(CellularState state)
00370 {
00371     _next_state = state;
00372     _retry_count = 0;
00373     _command_success = false;
00374 }
00375 
00376 void CellularConnectionFSM::retry_state_or_fail()
00377 {
00378     if (++_retry_count < MAX_RETRY_ARRAY_SIZE) {
00379         tr_debug("Retry State %s, retry %d/%d", get_state_string(_state), _retry_count, MAX_RETRY_ARRAY_SIZE);
00380         _event_timeout = _retry_timeout_array[_retry_count];
00381     } else {
00382         report_failure(get_state_string(_state));
00383         return;
00384     }
00385 }
00386 
00387 void CellularConnectionFSM::state_init()
00388 {
00389     // we should check that if power is already on then we can jump to device ready state
00390     _cellularDevice->set_timeout(TIMEOUT_POWER_ON);
00391     tr_info("Cellular state init (timeout %d ms)", TIMEOUT_POWER_ON);
00392     nsapi_error_t err = _power->is_device_ready();
00393     if (err != NSAPI_ERROR_OK ) {
00394         _event_timeout = _start_time;
00395         tr_info("Init state, waiting %d ms before POWER state)", _start_time);
00396         enter_to_state(STATE_POWER_ON);
00397     } else {
00398         tr_info("Device was ready to accept commands, jump to device ready");
00399         enter_to_state(STATE_DEVICE_READY);
00400     }
00401 }
00402 
00403 void CellularConnectionFSM::state_power_on()
00404 {
00405     _cellularDevice->set_timeout(TIMEOUT_POWER_ON);
00406     tr_info("Cellular power ON (timeout %d ms)", TIMEOUT_POWER_ON);
00407     if (power_on()) {
00408         enter_to_state(STATE_DEVICE_READY);
00409     } else {
00410         // retry to power on device
00411         retry_state_or_fail();
00412     }
00413 }
00414 
00415 bool CellularConnectionFSM::device_ready()
00416 {
00417     if (_cellularDevice->init_module(_serial) != NSAPI_ERROR_OK ) {
00418         return false;
00419     }
00420     tr_info("Cellular device ready");
00421     if (_event_status_cb) {
00422         _event_status_cb((nsapi_event_t)CellularDeviceReady, 0);
00423     }
00424     _power->remove_device_ready_urc_cb(mbed::callback(this, &CellularConnectionFSM::ready_urc_cb));
00425     _cellularDevice->close_power();
00426     _power = NULL;
00427     return true;
00428 }
00429 
00430 void CellularConnectionFSM::state_device_ready()
00431 {
00432     _cellularDevice->set_timeout(TIMEOUT_POWER_ON);
00433     if (_power->set_at_mode() == NSAPI_ERROR_OK ) {
00434         if (device_ready()) {
00435             enter_to_state(STATE_SIM_PIN);
00436         }
00437     } else {
00438         if (_retry_count == 0) {
00439             (void)_power->set_device_ready_urc_cb(mbed::callback(this, &CellularConnectionFSM::ready_urc_cb));
00440         }
00441         retry_state_or_fail();
00442     }
00443 }
00444 
00445 void CellularConnectionFSM::state_sim_pin()
00446 {
00447     _cellularDevice->set_timeout(TIMEOUT_SIM_PIN);
00448     tr_info("Sim state (timeout %d ms)", TIMEOUT_SIM_PIN);
00449     if (open_sim()) {
00450         bool success = false;
00451         for (int type = 0; type < CellularNetwork::C_MAX; type++) {
00452             if (!_network->set_registration_urc((CellularNetwork::RegistrationType)type, true)) {
00453                 success = true;
00454             }
00455         }
00456         if (!success) {
00457             tr_warn("Failed to set any URC's for registration");
00458             retry_state_or_fail();
00459             return;
00460         }
00461         if (_plmn) {
00462             enter_to_state(STATE_MANUAL_REGISTERING_NETWORK);
00463         } else {
00464             enter_to_state(STATE_REGISTERING_NETWORK);
00465         }
00466     } else {
00467         retry_state_or_fail();
00468     }
00469 }
00470 
00471 void CellularConnectionFSM::state_registering()
00472 {
00473     _cellularDevice->set_timeout(TIMEOUT_NETWORK);
00474     if (is_registered()) {
00475         // we are already registered, go to attach
00476         enter_to_state(STATE_ATTACHING_NETWORK);
00477     } else {
00478         _cellularDevice->set_timeout(TIMEOUT_REGISTRATION);
00479         if (!_command_success) {
00480             _command_success = (_network->set_registration() == NSAPI_ERROR_OK );
00481         }
00482         retry_state_or_fail();
00483     }
00484 }
00485 
00486 // only used when _plmn is set
00487 void CellularConnectionFSM::state_manual_registering_network()
00488 {
00489     _cellularDevice->set_timeout(TIMEOUT_REGISTRATION);
00490     tr_info("state_manual_registering_network");
00491     if (!_plmn_network_found) {
00492         if (is_registered() && is_registered_to_plmn()) {
00493             _plmn_network_found = true;
00494             enter_to_state(STATE_ATTACHING_NETWORK);
00495         } else {
00496             if (!_command_success) {
00497                 _command_success = (_network->set_registration(_plmn) == NSAPI_ERROR_OK );
00498             }
00499             retry_state_or_fail();
00500         }
00501     }
00502 }
00503 
00504 void CellularConnectionFSM::state_attaching()
00505 {
00506     _cellularDevice->set_timeout(TIMEOUT_CONNECT);
00507     if (_network->set_attach() == NSAPI_ERROR_OK ) {
00508         _cellularDevice->close_sim();
00509         _sim = NULL;
00510         enter_to_state(STATE_ACTIVATING_PDP_CONTEXT);
00511     } else {
00512         retry_state_or_fail();
00513     }
00514 }
00515 
00516 void CellularConnectionFSM::state_activating_pdp_context()
00517 {
00518     _cellularDevice->set_timeout(TIMEOUT_CONNECT);
00519     tr_info("Activate PDP Context (timeout %d ms)", TIMEOUT_CONNECT);
00520     if (_network->activate_context() == NSAPI_ERROR_OK ) {
00521         // when using modems stack connect is synchronous
00522         _next_state = STATE_CONNECTING_NETWORK;
00523     } else {
00524         retry_state_or_fail();
00525     }
00526 }
00527 
00528 void CellularConnectionFSM::state_connect_to_network()
00529 {
00530     _cellularDevice->set_timeout(TIMEOUT_CONNECT);
00531     tr_info("Connect to cellular network (timeout %d ms)", TIMEOUT_CONNECT);
00532     if (_network->connect() == NSAPI_ERROR_OK ) {
00533         _cellularDevice->set_timeout(TIMEOUT_NETWORK);
00534         tr_debug("Connected to cellular network, set at timeout (timeout %d ms)", TIMEOUT_NETWORK);
00535         // when using modems stack connect is synchronous
00536         _next_state = STATE_CONNECTED;
00537     } else {
00538         retry_state_or_fail();
00539     }
00540 }
00541 
00542 void CellularConnectionFSM::state_connected()
00543 {
00544     _cellularDevice->set_timeout(TIMEOUT_NETWORK);
00545     tr_debug("Cellular ready! (timeout %d ms)", TIMEOUT_NETWORK);
00546     if (_status_callback) {
00547         _status_callback(_state, _next_state);
00548     }
00549 }
00550 
00551 void CellularConnectionFSM::event()
00552 {
00553     _event_timeout = -1;
00554     switch (_state) {
00555         case STATE_INIT:
00556             state_init();
00557             break;
00558         case STATE_POWER_ON:
00559             state_power_on();
00560             break;
00561         case STATE_DEVICE_READY:
00562             state_device_ready();
00563             break;
00564         case STATE_SIM_PIN:
00565             state_sim_pin();
00566             break;
00567         case STATE_REGISTERING_NETWORK:
00568             state_registering();
00569             break;
00570         case STATE_MANUAL_REGISTERING_NETWORK:
00571             state_manual_registering_network();
00572             break;
00573         case STATE_ATTACHING_NETWORK:
00574             state_attaching();
00575             break;
00576         case STATE_ACTIVATING_PDP_CONTEXT:
00577             state_activating_pdp_context();
00578             break;
00579         case STATE_CONNECTING_NETWORK:
00580             state_connect_to_network();
00581             break;
00582         case STATE_CONNECTED:
00583             state_connected();
00584             break;
00585         default:
00586             MBED_ASSERT(0);
00587             break;
00588     }
00589 
00590     if (_next_state != _state || _event_timeout >= 0) {
00591         if (_next_state != _state) { // state exit condition
00592             tr_info("Cellular state from %s to %s", get_state_string((CellularConnectionFSM::CellularState)_state),
00593                     get_state_string((CellularConnectionFSM::CellularState)_next_state));
00594             if (_status_callback) {
00595                 if (!_status_callback(_state, _next_state)) {
00596                     return;
00597                 }
00598             }
00599         } else {
00600             tr_info("Cellular event in %d seconds", _event_timeout);
00601         }
00602         _state = _next_state;
00603         if (_event_timeout == -1) {
00604             _event_timeout = 0;
00605         }
00606         _event_id = _queue.call_in(_event_timeout * 1000, callback(this, &CellularConnectionFSM::event));
00607         if (!_event_id) {
00608             report_failure("Cellular event failure!");
00609             return;
00610         }
00611     }
00612 }
00613 
00614 nsapi_error_t CellularConnectionFSM::start_dispatch()
00615 {
00616     MBED_ASSERT(!_queue_thread);
00617 
00618     _queue_thread = new rtos::Thread(osPriorityNormal, 2048);
00619     if (!_queue_thread) {
00620         stop();
00621         return NSAPI_ERROR_NO_MEMORY ;
00622     }
00623     if (_queue_thread->start(callback(&_queue, &events::EventQueue::dispatch_forever)) != osOK) {
00624         stop();
00625         return NSAPI_ERROR_NO_MEMORY ;
00626     }
00627 
00628     return NSAPI_ERROR_OK ;
00629 }
00630 
00631 void CellularConnectionFSM::set_serial(UARTSerial *serial)
00632 {
00633     _serial = serial;
00634 }
00635 
00636 void CellularConnectionFSM::set_callback(mbed::Callback<bool(int, int)> status_callback)
00637 {
00638     _status_callback = status_callback;
00639 }
00640 
00641 void CellularConnectionFSM::attach(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb)
00642 {
00643     MBED_ASSERT(_network);
00644     _event_status_cb = status_cb;
00645     if (status_cb) {
00646         _network->attach(callback(this, &CellularConnectionFSM::network_callback));
00647     } else {
00648         _network->attach(NULL);
00649     }
00650 }
00651 
00652 void CellularConnectionFSM::network_callback(nsapi_event_t ev, intptr_t ptr)
00653 {
00654     tr_info("FSM: network_callback called with event: %d, intptr: %d, _state: %s", ev, ptr, get_state_string(_state));
00655     if ((cellular_connection_status_t)ev == CellularRegistrationStatusChanged &&
00656             (_state == STATE_REGISTERING_NETWORK || _state == STATE_MANUAL_REGISTERING_NETWORK)) {
00657         // expect packet data so only these states are valid
00658         if (ptr == CellularNetwork::RegisteredHomeNetwork || ptr == CellularNetwork::RegisteredRoaming) {
00659             if (_plmn) {
00660                 if (is_registered_to_plmn()) {
00661                     if (!_plmn_network_found) {
00662                         _plmn_network_found = true;
00663                         _queue.cancel(_event_id);
00664                         continue_from_state(STATE_ATTACHING_NETWORK);
00665                     }
00666                 }
00667             } else {
00668                 _queue.cancel(_event_id);
00669                 continue_from_state(STATE_ATTACHING_NETWORK);
00670             }
00671         }
00672     }
00673 
00674     if (_event_status_cb) {
00675         _event_status_cb(ev, ptr);
00676     }
00677 }
00678 
00679 void CellularConnectionFSM::ready_urc_cb()
00680 {
00681     tr_debug("Device ready URC func called");
00682     if (_state == STATE_DEVICE_READY && _power->set_at_mode() == NSAPI_ERROR_OK ) {
00683         tr_debug("State was STATE_DEVICE_READY and at mode ready, cancel state and move to next");
00684         if (device_ready()) {
00685             _queue.cancel(_event_id);
00686             continue_from_state(STATE_SIM_PIN);
00687         }
00688     }
00689 }
00690 
00691 events::EventQueue *CellularConnectionFSM::get_queue()
00692 {
00693     return &_queue;
00694 }
00695 
00696 CellularNetwork *CellularConnectionFSM::get_network()
00697 {
00698     return _network;
00699 }
00700 
00701 CellularDevice *CellularConnectionFSM::get_device()
00702 {
00703     return _cellularDevice;
00704 }
00705 
00706 CellularSIM *CellularConnectionFSM::get_sim()
00707 {
00708     return _sim;
00709 }
00710 
00711 NetworkStack *CellularConnectionFSM::get_stack()
00712 {
00713     return _cellularDevice->get_stack();
00714 }
00715 
00716 void CellularConnectionFSM::set_retry_timeout_array(uint16_t timeout[], int array_len)
00717 {
00718     _retry_array_length = array_len > MAX_RETRY_ARRAY_SIZE ? MAX_RETRY_ARRAY_SIZE : array_len;
00719 
00720     for (int i = 0; i < _retry_array_length; i++) {
00721         _retry_timeout_array[i] = timeout[i];
00722     }
00723 }
00724 
00725 } // namespace
00726 
00727 #endif // CELLULAR_DEVICE