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