Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers CellularContext.cpp Source File

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