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.
EasyCellularConnection.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 "CellularTargets.h" 00019 #ifdef CELLULAR_DEVICE 00020 00021 #if NSAPI_PPP_AVAILABLE 00022 #include "nsapi_ppp.h" 00023 #endif 00024 00025 #include "CellularConnectionFSM.h" 00026 #include "CellularDevice.h" 00027 00028 #include "EasyCellularConnection.h" 00029 #include "CellularLog.h" 00030 #include "mbed_wait_api.h" 00031 00032 #if USE_APN_LOOKUP 00033 #include "APN_db.h" 00034 #endif //USE_APN_LOOKUP 00035 00036 namespace mbed { 00037 00038 bool EasyCellularConnection::cellular_status(int state, int next_state) 00039 { 00040 tr_info("cellular_status: %s ==> %s", _cellularConnectionFSM->get_state_string((CellularConnectionFSM::CellularState)state), 00041 _cellularConnectionFSM->get_state_string((CellularConnectionFSM::CellularState)next_state)); 00042 00043 if (_target_state == state) { 00044 tr_info("Target state reached: %s", _cellularConnectionFSM->get_state_string(_target_state)); 00045 (void)_cellularSemaphore.release(); 00046 return false; // return false -> state machine is halted 00047 } 00048 00049 // only in case of an error or when connected is reached state and next_state can be the same. 00050 // Release semaphore to return application instead of waiting for semaphore to complete. 00051 if (state == next_state) { 00052 tr_error("cellular_status: state and next_state are same, release semaphore as this is an error in state machine"); 00053 _stm_error = true; 00054 (void)_cellularSemaphore.release(); 00055 return false; // return false -> state machine is halted 00056 } 00057 00058 return true; 00059 } 00060 00061 void EasyCellularConnection::network_callback(nsapi_event_t ev, intptr_t ptr) 00062 { 00063 if (ev == NSAPI_EVENT_CONNECTION_STATUS_CHANGE ) { 00064 if (ptr == NSAPI_STATUS_GLOBAL_UP ) { 00065 _is_connected = true; 00066 } else { 00067 _is_connected = false; 00068 } 00069 } 00070 if (_status_cb) { 00071 _status_cb(ev, ptr); 00072 } 00073 } 00074 00075 EasyCellularConnection::EasyCellularConnection(bool debug) : 00076 _is_connected(false), _is_initialized(false), _stm_error(false), 00077 _target_state(CellularConnectionFSM::STATE_POWER_ON), 00078 _cellularSerial(MDMTXD, MDMRXD, MBED_CONF_PLATFORM_DEFAULT_SERIAL_BAUD_RATE), _cellularSemaphore(0), 00079 _cellularConnectionFSM(0), _credentials_err(NSAPI_ERROR_OK ), _status_cb(0) 00080 { 00081 tr_info("EasyCellularConnection()"); 00082 #if USE_APN_LOOKUP 00083 _credentials_set = false; 00084 #endif // #if USE_APN_LOOKUP 00085 modem_debug_on(debug); 00086 } 00087 00088 EasyCellularConnection::~EasyCellularConnection() 00089 { 00090 if (_cellularConnectionFSM) { 00091 _cellularConnectionFSM->set_callback(NULL); 00092 _cellularConnectionFSM->attach(NULL); 00093 delete _cellularConnectionFSM; 00094 } 00095 } 00096 00097 nsapi_error_t EasyCellularConnection::init() 00098 { 00099 nsapi_error_t err = NSAPI_ERROR_OK ; 00100 _stm_error = false; 00101 if (!_is_initialized) { 00102 #if defined (MDMRTS) && defined (MDMCTS) 00103 _cellularSerial.set_flow_control(SerialBase::RTSCTS, MDMRTS, MDMCTS); 00104 #endif 00105 _cellularConnectionFSM = new CellularConnectionFSM(); 00106 _cellularConnectionFSM->set_serial(&_cellularSerial); 00107 _cellularConnectionFSM->set_callback(callback(this, &EasyCellularConnection::cellular_status)); 00108 00109 err = _cellularConnectionFSM->init(); 00110 00111 if (err == NSAPI_ERROR_OK ) { 00112 err = _cellularConnectionFSM->start_dispatch(); 00113 _cellularConnectionFSM->attach(callback(this, &EasyCellularConnection::network_callback)); 00114 } 00115 _is_initialized = true; 00116 } 00117 00118 return err; 00119 } 00120 00121 void EasyCellularConnection::set_credentials(const char *apn, const char *uname, const char *pwd) 00122 { 00123 if (apn && strlen(apn) > 0) { 00124 _credentials_err = init(); 00125 00126 if (_credentials_err) { 00127 return; 00128 } 00129 CellularNetwork *network = _cellularConnectionFSM->get_network(); 00130 if (network) { 00131 _credentials_err = network->set_credentials(apn, uname, pwd); 00132 #if USE_APN_LOOKUP 00133 if (_credentials_err == NSAPI_ERROR_OK ) { 00134 _credentials_set = true; 00135 } 00136 #endif // #if USE_APN_LOOKUP 00137 } else { 00138 //if get_network() returns NULL it means there was not enough memory for 00139 //an AT_CellularNetwork element during CellularConnectionFSM initialization 00140 tr_error("There was not enough memory during CellularConnectionFSM initialization"); 00141 } 00142 } 00143 } 00144 00145 void EasyCellularConnection::set_sim_pin(const char *sim_pin) 00146 { 00147 if (sim_pin && strlen(sim_pin) > 0) { 00148 if (!_cellularConnectionFSM) { 00149 _credentials_err = init(); 00150 00151 if (_credentials_err) { 00152 return; 00153 } 00154 } 00155 _cellularConnectionFSM->set_sim_pin(sim_pin); 00156 } 00157 } 00158 00159 nsapi_error_t EasyCellularConnection::connect(const char *sim_pin, const char *apn, const char *uname, const char *pwd) 00160 { 00161 if (_is_connected) { 00162 return NSAPI_ERROR_IS_CONNECTED ; 00163 } 00164 00165 set_credentials(apn, uname, pwd); 00166 if (_credentials_err) { 00167 return _credentials_err; 00168 } 00169 00170 if (sim_pin) { 00171 set_sim_pin(sim_pin); 00172 } 00173 00174 return connect(); 00175 } 00176 00177 nsapi_error_t EasyCellularConnection::check_connect() 00178 { 00179 if (_is_connected) { 00180 return NSAPI_ERROR_IS_CONNECTED ; 00181 } 00182 00183 // there was an error while setting credentials but it's a void function so check error here... 00184 if (_credentials_err) { 00185 return _credentials_err; 00186 } 00187 00188 nsapi_error_t err = init(); 00189 if (err) { 00190 return err; 00191 } 00192 00193 return NSAPI_ERROR_OK ; 00194 } 00195 00196 nsapi_error_t EasyCellularConnection::connect() 00197 { 00198 nsapi_error_t err = check_connect(); 00199 if (err) { 00200 return err; 00201 } 00202 #if USE_APN_LOOKUP 00203 if (!_credentials_set) { 00204 _target_state = CellularConnectionFSM::STATE_SIM_PIN; 00205 err = _cellularConnectionFSM->continue_to_state(_target_state); 00206 if (err == NSAPI_ERROR_OK ) { 00207 int sim_wait = _cellularSemaphore.wait(60 * 1000); // reserve 60 seconds to access to SIM 00208 if (sim_wait != 1 || _stm_error) { 00209 tr_error("NO SIM ACCESS"); 00210 err = NSAPI_ERROR_NO_CONNECTION ; 00211 } else { 00212 char imsi[MAX_IMSI_LENGTH + 1]; 00213 wait(1); // need to wait to access SIM in some modems 00214 err = _cellularConnectionFSM->get_sim()->get_imsi(imsi); 00215 if (err == NSAPI_ERROR_OK ) { 00216 const char *apn_config = apnconfig(imsi); 00217 if (apn_config) { 00218 const char *apn = _APN_GET(apn_config); 00219 const char *uname = _APN_GET(apn_config); 00220 const char *pwd = _APN_GET(apn_config); 00221 tr_info("Looked up APN %s", apn); 00222 err = _cellularConnectionFSM->get_network()->set_credentials(apn, uname, pwd); 00223 } 00224 } 00225 } 00226 } 00227 if (err) { 00228 tr_error("APN lookup failed"); 00229 return err; 00230 } 00231 } 00232 #endif // USE_APN_LOOKUP 00233 00234 _target_state = CellularConnectionFSM::STATE_CONNECTED; 00235 err = _cellularConnectionFSM->continue_to_state(_target_state); 00236 if (err == NSAPI_ERROR_OK ) { 00237 int ret_wait = _cellularSemaphore.wait(10 * 60 * 1000); // cellular network searching may take several minutes 00238 if (ret_wait != 1 || _stm_error) { 00239 tr_info("No cellular connection"); 00240 err = NSAPI_ERROR_NO_CONNECTION ; 00241 } 00242 } 00243 00244 return err; 00245 } 00246 00247 nsapi_error_t EasyCellularConnection::disconnect() 00248 { 00249 _credentials_err = NSAPI_ERROR_OK ; 00250 _is_connected = false; 00251 _is_initialized = false; 00252 _stm_error = false; 00253 #if USE_APN_LOOKUP 00254 _credentials_set = false; 00255 #endif // #if USE_APN_LOOKUP 00256 00257 nsapi_error_t err = NSAPI_ERROR_OK ; 00258 if (_cellularConnectionFSM && _cellularConnectionFSM->get_network()) { 00259 err = _cellularConnectionFSM->get_network()->disconnect(); 00260 } 00261 00262 if (err == NSAPI_ERROR_OK ) { 00263 delete _cellularConnectionFSM; 00264 _cellularConnectionFSM = NULL; 00265 } 00266 00267 return err; 00268 } 00269 00270 bool EasyCellularConnection::is_connected() 00271 { 00272 return _is_connected; 00273 } 00274 00275 const char *EasyCellularConnection::get_ip_address() 00276 { 00277 if (_cellularConnectionFSM) { 00278 CellularNetwork *network = _cellularConnectionFSM->get_network(); 00279 if (!network) { 00280 return NULL; 00281 } 00282 return _cellularConnectionFSM->get_network()->get_ip_address(); 00283 } else { 00284 return NULL; 00285 } 00286 } 00287 00288 const char *EasyCellularConnection::get_netmask() 00289 { 00290 if (_cellularConnectionFSM) { 00291 CellularNetwork *network = _cellularConnectionFSM->get_network(); 00292 if (!network) { 00293 return NULL; 00294 } 00295 return network->get_netmask(); 00296 } else { 00297 return NULL; 00298 } 00299 } 00300 00301 const char *EasyCellularConnection::get_gateway() 00302 { 00303 if (_cellularConnectionFSM) { 00304 CellularNetwork *network = _cellularConnectionFSM->get_network(); 00305 if (!network) { 00306 return NULL; 00307 } 00308 return network->get_gateway(); 00309 } else { 00310 return NULL; 00311 } 00312 } 00313 00314 void EasyCellularConnection::attach(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb) 00315 { 00316 _status_cb = status_cb; 00317 } 00318 00319 void EasyCellularConnection::modem_debug_on(bool on) 00320 { 00321 if (_cellularConnectionFSM) { 00322 CellularDevice *dev = _cellularConnectionFSM->get_device(); 00323 if (dev) { 00324 dev->modem_debug_on(on); 00325 } 00326 } 00327 } 00328 00329 void EasyCellularConnection::set_plmn(const char *plmn) 00330 { 00331 if (plmn && strlen(plmn) > 0) { 00332 if (!_cellularConnectionFSM) { 00333 _credentials_err = init(); 00334 00335 if (_credentials_err) { 00336 return; 00337 } 00338 } 00339 _cellularConnectionFSM->set_plmn(plmn); 00340 } 00341 } 00342 00343 NetworkStack *EasyCellularConnection::get_stack() 00344 { 00345 if (_cellularConnectionFSM) { 00346 return _cellularConnectionFSM->get_stack(); 00347 } else { 00348 return NULL; 00349 } 00350 } 00351 00352 CellularDevice *EasyCellularConnection::get_device() 00353 { 00354 return _cellularConnectionFSM->get_device(); 00355 } 00356 00357 UARTSerial *EasyCellularConnection::get_serial() 00358 { 00359 return &_cellularSerial; 00360 } 00361 00362 } // namespace 00363 00364 #endif // CELLULAR_DEVICE
Generated on Tue Aug 9 2022 00:37:05 by
