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
CellularContext.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 #include "CellularContext.h" 00018 #include "CellularLog.h" 00019 #include "ThisThread.h" 00020 00021 MBED_WEAK CellularInterface *CellularInterface::get_target_default_instance() 00022 { 00023 return mbed::CellularContext::get_default_instance(); 00024 } 00025 00026 namespace mbed { 00027 00028 MBED_WEAK CellularContext *CellularContext::get_default_instance() 00029 { 00030 CellularDevice *dev = CellularDevice::get_default_instance(); 00031 if (!dev) { 00032 return NULL; 00033 } 00034 00035 static CellularContext *context = dev->create_context(NULL, NULL, MBED_CONF_CELLULAR_CONTROL_PLANE_OPT); 00036 #if (DEVICE_SERIAL && DEVICE_INTERRUPTIN) || defined(DOXYGEN_ONLY) 00037 #if defined(MDMDCD) && defined(MDM_PIN_POLARITY) 00038 context->set_file_handle(static_cast<UARTSerial *>(&dev->get_file_handle()), MDMDCD, MDM_PIN_POLARITY); 00039 #endif // #if defined(MDMDCD) && defined(MDM_PIN_POLARITY) 00040 #endif // #if DEVICE_SERIAL 00041 return context; 00042 } 00043 00044 MBED_WEAK CellularContext *CellularContext::get_default_nonip_instance() 00045 { 00046 // Uses default APN, uname, password from mbed_app.json 00047 CellularDevice *dev = CellularDevice::get_default_instance(); 00048 if (!dev) { 00049 return NULL; 00050 } 00051 00052 static CellularContext *context = dev->create_context(NULL, NULL, MBED_CONF_CELLULAR_CONTROL_PLANE_OPT, true); 00053 #if (DEVICE_SERIAL && DEVICE_INTERRUPTIN) || defined(DOXYGEN_ONLY) 00054 #if defined(MDMDCD) && defined(MDM_PIN_POLARITY) 00055 context->set_file_handle(static_cast<UARTSerial *>(&dev->get_file_handle()), MDMDCD, MDM_PIN_POLARITY); 00056 #endif // #if defined(MDMDCD) && defined(MDM_PIN_POLARITY) 00057 #endif // #if DEVICE_SERIAL 00058 return context; 00059 } 00060 00061 CellularContext::CellularContext() : _next(0), _stack(0), _pdp_type(DEFAULT_PDP_TYPE), 00062 _authentication_type(CellularContext::CHAP), _connect_status(NSAPI_STATUS_DISCONNECTED ), _status_cb(0), 00063 _cid(-1), _new_context_set(false), _is_context_active(false), _is_context_activated(false), 00064 _apn(0), _uname(0), _pwd(0), _dcd_pin(NC), _active_high(false), _cp_netif(0), _retry_array_length(0), 00065 _retry_count(0), _device(0), _nw(0), _is_blocking(true), _nonip_req(false), _cp_in_use(false) 00066 { 00067 memset(_retry_timeout_array, 0, sizeof(_retry_timeout_array)); 00068 } 00069 00070 void CellularContext::cp_data_received() 00071 { 00072 _cp_netif->data_received(); 00073 } 00074 00075 CellularDevice *CellularContext::get_device() const 00076 { 00077 return _device; 00078 } 00079 00080 int CellularContext::get_cid() const 00081 { 00082 return _cid; 00083 } 00084 00085 void CellularContext::set_authentication_type(AuthenticationType type) 00086 { 00087 _authentication_type = type; 00088 } 00089 00090 void CellularContext::validate_ip_address() 00091 { 00092 const int IP_MAX_TRIES = 10; // maximum of 2 seconds as we wait 200ms between tries 00093 const int IP_WAIT_INTERVAL = 200; // 200 ms between retries 00094 SocketAddress ip; 00095 int i = 0; 00096 00097 while (1) { 00098 get_ip_address (&ip); 00099 if (ip || i >= IP_MAX_TRIES) { 00100 if (ip.get_ip_address() == NULL) { 00101 tr_warning("Connected but no local ip address"); 00102 } else { 00103 tr_info("Cellular local IP: %s", ip.get_ip_address()); 00104 } 00105 break; 00106 } 00107 rtos::ThisThread::sleep_for(IP_WAIT_INTERVAL); 00108 i++; 00109 } 00110 } 00111 00112 void CellularContext::do_connect_with_retry() 00113 { 00114 if (_cb_data.final_try) { 00115 _cb_data.final_try = false; 00116 _cb_data.error = NSAPI_ERROR_NO_CONNECTION ; 00117 call_network_cb(NSAPI_STATUS_DISCONNECTED ); 00118 return; 00119 } 00120 do_connect(); 00121 if (_cb_data.error == NSAPI_ERROR_OK ) { 00122 #if !NSAPI_PPP_AVAILABLE 00123 // Some modems don't get the ip address right after connect so we must 00124 // validate it but even if we don't get ip we still send NSAPI_STATUS_GLOBAL_UP 00125 if (!_nonip_req && !_cp_in_use) { // don't validate if non-ip case 00126 validate_ip_address(); 00127 } 00128 call_network_cb(NSAPI_STATUS_GLOBAL_UP ); 00129 #endif 00130 return; 00131 } 00132 00133 if (_retry_count == 0) { 00134 _device->get_retry_timeout_array(_retry_timeout_array, _retry_array_length); 00135 } 00136 00137 if (_is_blocking) { 00138 while (_retry_count < _retry_array_length) { 00139 tr_debug("SYNC do_connect failed with %d, retry after %d seconds", _cb_data.error, _retry_timeout_array[_retry_count]); 00140 rtos::ThisThread::sleep_for(_retry_timeout_array[_retry_count] * 1000); 00141 do_connect(); 00142 if (_cb_data.error == NSAPI_ERROR_OK ) { 00143 return; 00144 } 00145 _retry_count++; 00146 } 00147 } else { 00148 if (_retry_count < _retry_array_length) { 00149 if (_retry_count == _retry_array_length - 1) { 00150 // set the flag that this is the last try for ppp connect / pdp context activate 00151 _cb_data.final_try = true; 00152 } 00153 tr_debug("ASYNC do_connect failed with %d, retry after %d seconds", _cb_data.error, _retry_timeout_array[_retry_count]); 00154 int id = _device->get_queue()->call_in(_retry_timeout_array[_retry_count] * 1000, this, &CellularContext::do_connect_with_retry); 00155 if (id == 0) { 00156 tr_error("Failed call via eventqueue in do_connect_with_retry()"); 00157 #if !NSAPI_PPP_AVAILABLE 00158 _cb_data.final_try = true; 00159 _cb_data.error = NSAPI_ERROR_NO_MEMORY ; 00160 // in PPP mode we did not activate any context, just searched the correct _cid 00161 if (_status_cb) { 00162 _status_cb((nsapi_event_t)CellularActivatePDPContext, (intptr_t)&_cb_data); 00163 } 00164 _cb_data.final_try = false; 00165 _cb_data.error = NSAPI_ERROR_OK ; 00166 #else 00167 call_network_cb(NSAPI_STATUS_DISCONNECTED ); 00168 #endif // !NSAPI_PPP_AVAILABLE 00169 } 00170 _retry_count++; 00171 return; // don't call NSAPI_STATUS_DISCONNECTED in every failure, only the last one. 00172 } 00173 } 00174 00175 #if NSAPI_PPP_AVAILABLE 00176 if (_cb_data.error != NSAPI_ERROR_OK ) { 00177 tr_error("Failed to open data channel!"); 00178 call_network_cb(NSAPI_STATUS_DISCONNECTED ); 00179 } 00180 #endif // #if NSAPI_PPP_AVAILABLE 00181 } 00182 00183 void CellularContext::do_connect() 00184 { 00185 _cb_data.error = NSAPI_ERROR_OK ; 00186 } 00187 00188 void CellularContext::call_network_cb(nsapi_connection_status_t status) 00189 { 00190 if (_connect_status != status) { 00191 _connect_status = status; 00192 if (_status_cb) { 00193 _status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE , _connect_status); 00194 } 00195 if (_nw && _connect_status == NSAPI_STATUS_DISCONNECTED ) { 00196 tr_info("CellularContext disconnected"); 00197 } 00198 } 00199 } 00200 00201 } // namespace mbed
Generated on Tue Jul 12 2022 13:54:05 by
