Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers CellularDevice.cpp Source File

CellularDevice.cpp

00001 /*
00002  * Copyright (c) 2018, 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 "CellularDevice.h"
00019 #include "CellularContext.h"
00020 #include "CellularUtil.h"
00021 #include "CellularLog.h"
00022 #include "events/EventQueue.h"
00023 
00024 namespace mbed {
00025 
00026 MBED_WEAK CellularDevice *CellularDevice::get_default_instance()
00027 {
00028     return get_target_default_instance();
00029 }
00030 
00031 MBED_WEAK CellularDevice *CellularDevice::get_target_default_instance()
00032 {
00033     return NULL;
00034 }
00035 
00036 CellularDevice::CellularDevice(FileHandle *fh) : _network_ref_count(0),
00037 #if MBED_CONF_CELLULAR_USE_SMS
00038     _sms_ref_count(0),
00039 #endif //MBED_CONF_CELLULAR_USE_SMS
00040     _info_ref_count(0), _fh(fh), _queue(10 * EVENTS_EVENT_SIZE), _state_machine(0),
00041     _nw(0), _status_cb(0), _property_array(0)
00042 {
00043     MBED_ASSERT(fh);
00044     set_sim_pin(NULL);
00045     set_plmn(NULL);
00046 }
00047 
00048 CellularDevice::~CellularDevice()
00049 {
00050     tr_debug("CellularDevice destruct");
00051     delete _state_machine;
00052 }
00053 
00054 void CellularDevice::stop()
00055 {
00056     MBED_ASSERT(_state_machine);
00057     _state_machine->stop();
00058 }
00059 
00060 FileHandle &CellularDevice::get_file_handle() const
00061 {
00062     return *_fh;
00063 }
00064 
00065 events::EventQueue *CellularDevice::get_queue()
00066 {
00067     return &_queue;
00068 }
00069 
00070 CellularContext *CellularDevice::get_context_list() const
00071 {
00072     return NULL;
00073 }
00074 
00075 void CellularDevice::get_retry_timeout_array(uint16_t *timeout, int &array_len) const
00076 {
00077     if (_state_machine && timeout) {
00078         _state_machine->get_retry_timeout_array(timeout, array_len);
00079     }
00080 }
00081 
00082 void CellularDevice::set_sim_pin(const char *sim_pin)
00083 {
00084     if (sim_pin) {
00085         strncpy(_sim_pin, sim_pin, sizeof(_sim_pin));
00086         _sim_pin[sizeof(_sim_pin) - 1] = '\0';
00087     } else {
00088         memset(_sim_pin, 0, sizeof(_sim_pin));
00089     }
00090 }
00091 
00092 void CellularDevice::set_plmn(const char *plmn)
00093 {
00094     if (plmn) {
00095         strncpy(_plmn, plmn, sizeof(_plmn));
00096         _plmn[sizeof(_plmn) - 1] = '\0';
00097     } else {
00098         memset(_plmn, 0, sizeof(_plmn));
00099     }
00100 }
00101 
00102 nsapi_error_t CellularDevice::set_device_ready()
00103 {
00104     return start_state_machine(CellularStateMachine::STATE_DEVICE_READY);
00105 }
00106 
00107 nsapi_error_t CellularDevice::set_sim_ready()
00108 {
00109     return start_state_machine(CellularStateMachine::STATE_SIM_PIN);
00110 }
00111 
00112 nsapi_error_t CellularDevice::register_to_network()
00113 {
00114     return start_state_machine(CellularStateMachine::STATE_REGISTERING_NETWORK);
00115 }
00116 
00117 nsapi_error_t CellularDevice::attach_to_network()
00118 {
00119     return start_state_machine(CellularStateMachine::STATE_ATTACHING_NETWORK);
00120 }
00121 
00122 nsapi_error_t CellularDevice::create_state_machine()
00123 {
00124     nsapi_error_t err = NSAPI_ERROR_OK ;
00125     if (!_state_machine) {
00126         _nw = open_network(_fh);
00127         // Attach to network so we can get update status from the network
00128         _nw->attach(callback(this, &CellularDevice::stm_callback));
00129         _state_machine = new CellularStateMachine(*this, *get_queue(), *_nw);
00130         _state_machine->set_cellular_callback(callback(this, &CellularDevice::stm_callback));
00131         if (strlen(_plmn)) {
00132             _state_machine->set_plmn(_plmn);
00133         }
00134         if (strlen(_sim_pin)) {
00135             _state_machine->set_sim_pin(_sim_pin);
00136         }
00137     }
00138     err = _state_machine->start_dispatch();
00139     if (err) {
00140         tr_error("Start state machine failed.");
00141         delete _state_machine;
00142         _state_machine = NULL;
00143         return err;
00144     }
00145     return err;
00146 }
00147 
00148 nsapi_error_t CellularDevice::start_state_machine(CellularStateMachine::CellularState target_state)
00149 {
00150     _mutex.lock();
00151     nsapi_error_t err = create_state_machine();
00152     if (err) {
00153         _mutex.unlock();
00154         return err;
00155     }
00156 
00157     CellularStateMachine::CellularState current_state, targeted_state;
00158 
00159     bool is_running = _state_machine->get_current_status(current_state, targeted_state);
00160 
00161     if (current_state >= target_state) { // can stm be in this state but failed?
00162         _mutex.unlock();
00163         return NSAPI_ERROR_ALREADY ;
00164     } else if (is_running && targeted_state >= target_state) {
00165         _mutex.unlock();
00166         return NSAPI_ERROR_IN_PROGRESS ;
00167     }
00168 
00169     err = _state_machine->run_to_state(target_state);
00170     _mutex.unlock();
00171 
00172     return err;
00173 }
00174 
00175 void CellularDevice::attach(Callback<void(nsapi_event_t, intptr_t)> status_cb)
00176 {
00177     _status_cb = status_cb;
00178 }
00179 
00180 void CellularDevice::stm_callback(nsapi_event_t ev, intptr_t ptr)
00181 {
00182     cellular_callback(ev, ptr);
00183 }
00184 
00185 void CellularDevice::cellular_callback(nsapi_event_t ev, intptr_t ptr, CellularContext *ctx)
00186 {
00187     if (ev >= NSAPI_EVENT_CELLULAR_STATUS_BASE  && ev <= NSAPI_EVENT_CELLULAR_STATUS_END ) {
00188         cellular_connection_status_t cell_ev = (cellular_connection_status_t)ev;
00189         cell_callback_data_t *ptr_data = (cell_callback_data_t *)ptr;
00190         (void)ptr_data; // avoid compile warning, used only for debugging
00191         if (cell_ev == CellularStateRetryEvent) {
00192             tr_debug("callback: CellularStateRetryEvent, err: %d, data: %d, retrycount: %d", ptr_data->error, ptr_data->status_data, *(const int *)ptr_data->data);
00193         } else {
00194             tr_debug("callback: %d, err: %d, data: %d", ev, ptr_data->error, ptr_data->status_data);
00195         }
00196         if (cell_ev == CellularRegistrationStatusChanged && _state_machine) {
00197             // broadcast only network registration changes to state machine
00198             _state_machine->cellular_event_changed(ev, ptr);
00199         }
00200     } else {
00201         tr_debug("callback: %d, ptr: %d", ev, ptr);
00202         if (ev == NSAPI_EVENT_CONNECTION_STATUS_CHANGE  && ptr == NSAPI_STATUS_DISCONNECTED ) {
00203             // we have been disconnected, reset state machine so that application can start connect sequence again
00204             if (_state_machine) {
00205                 CellularStateMachine::CellularState current_state, targeted_state;
00206                 bool is_running = _state_machine->get_current_status(current_state, targeted_state);
00207                 if (!is_running) {
00208                     _state_machine->reset();
00209                 }
00210             }
00211         }
00212     }
00213 
00214     // broadcast network and cellular changes to state machine and CellularContext.
00215     CellularContext *curr = get_context_list();
00216     while (curr) {
00217         if (ctx) {
00218             if (ctx == curr) {
00219                 curr->cellular_callback(ev, ptr);
00220                 break;
00221             }
00222         } else {
00223             curr->cellular_callback(ev, ptr);
00224         }
00225         curr = curr->_next;
00226     }
00227 
00228     // forward to callback function if set by attach(...).
00229     if (_status_cb) {
00230         _status_cb(ev, ptr);
00231     }
00232 }
00233 
00234 nsapi_error_t CellularDevice::shutdown()
00235 {
00236     if (_state_machine) {
00237         _state_machine->stop();
00238     }
00239     CellularContext *curr = get_context_list();
00240     while (curr) {
00241         if (curr->is_connected()) {
00242             curr->disconnect();
00243         }
00244         curr->cellular_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE , NSAPI_STATUS_DISCONNECTED );
00245         curr = (CellularContext *)curr->_next;
00246     }
00247     return NSAPI_ERROR_OK ;
00248 }
00249 
00250 void CellularDevice::set_retry_timeout_array(const uint16_t timeout[], int array_len)
00251 {
00252     if (create_state_machine() == NSAPI_ERROR_OK ) {
00253         _state_machine->set_retry_timeout_array(timeout, array_len);
00254     }
00255 }
00256 
00257 nsapi_error_t CellularDevice::clear()
00258 {
00259     return NSAPI_ERROR_OK ;
00260 }
00261 
00262 
00263 } // namespace mbed