Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
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
Generated on Tue Jul 12 2022 13:54:05 by
