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