Library that implements the CellularInterface using PPP and LWIP on the mbed MCU. May be used on the C027 and C030 (non-N2xx flavour) boards from mbed 5.5 onwards.
Dependents: example-ublox-cellular-interface HelloMQTT example-ublox-cellular-interface_r410M example-ublox-mbed-client
UbloxPPPCellularInterface.cpp
00001 /* Copyright (c) 2017 ublox Limited 00002 * 00003 * Licensed under the Apache License, Version 2.0 (the "License"); 00004 * you may not use this file except in compliance with the License. 00005 * You may obtain a copy of the License at 00006 * 00007 * http://www.apache.org/licenses/LICENSE-2.0 00008 * 00009 * Unless required by applicable law or agreed to in writing, software 00010 * distributed under the License is distributed on an "AS IS" BASIS, 00011 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00012 * See the License for the specific language governing permissions and 00013 * limitations under the License. 00014 */ 00015 00016 #include "cellular/onboard_modem_api.h" 00017 #include "nsapi_ppp.h" 00018 #include "utils/APN_db.h" 00019 #include "UbloxPPPCellularInterface.h" 00020 #ifdef FEATURE_COMMON_PAL 00021 #include "mbed_trace.h" 00022 #define TRACE_GROUP "UPCI" 00023 #else 00024 #define tr_debug(format, ...) debug_if(_debug_trace_on, format "\n", ## __VA_ARGS__) 00025 #define tr_info(format, ...) debug_if(_debug_trace_on, format "\n", ## __VA_ARGS__) 00026 #define tr_warn(format, ...) debug_if(_debug_trace_on, format "\n", ## __VA_ARGS__) 00027 #define tr_error(format, ...) debug_if(_debug_trace_on, format "\n", ## __VA_ARGS__) 00028 #endif 00029 00030 #if NSAPI_PPP_AVAILABLE 00031 00032 /********************************************************************** 00033 * PRIVATE METHODS 00034 **********************************************************************/ 00035 00036 // Send the credentials to the modem. 00037 nsapi_error_t UbloxPPPCellularInterface::setup_context_and_credentials() 00038 { 00039 nsapi_error_t nsapi_error = NSAPI_ERROR_PARAMETER; 00040 const char *auth = _uname && _pwd ? "CHAP:" : ""; 00041 LOCK(); 00042 00043 if (_apn) { 00044 // TODO: IPV6 00045 if (_at->send("AT+CGDCONT=1,\"%s\",\"%s%s\"", "IP", auth, _apn) && 00046 _at->recv("OK")) { 00047 nsapi_error = NSAPI_ERROR_OK; 00048 // C030 needs a short delay before the connection is triggered 00049 wait_ms(100); 00050 } 00051 } 00052 00053 UNLOCK(); 00054 return nsapi_error; 00055 00056 } 00057 00058 // Enter data mode. 00059 bool UbloxPPPCellularInterface::set_atd() 00060 { 00061 bool success; 00062 LOCK(); 00063 00064 success = _at->send("ATD*99***1#") && _at->recv("CONNECT"); 00065 00066 UNLOCK(); 00067 return success; 00068 } 00069 00070 /********************************************************************** 00071 * PROTECTED METHODS 00072 **********************************************************************/ 00073 00074 // Gain access to the underlying network stack. 00075 NetworkStack *UbloxPPPCellularInterface::get_stack() 00076 { 00077 return nsapi_ppp_get_stack(); 00078 } 00079 00080 // Get the next set of credentials, based on IMSI. 00081 void UbloxPPPCellularInterface::get_next_credentials(const char ** config) 00082 { 00083 if (*config) { 00084 _apn = _APN_GET(*config); 00085 _uname = _APN_GET(*config); 00086 _pwd = _APN_GET(*config); 00087 } 00088 00089 _apn = _apn ? _apn : ""; 00090 _uname = _uname ? _uname : ""; 00091 _pwd = _pwd ? _pwd : ""; 00092 } 00093 00094 /********************************************************************** 00095 * PUBLIC METHODS 00096 **********************************************************************/ 00097 00098 // Constructor. 00099 UbloxPPPCellularInterface::UbloxPPPCellularInterface(PinName tx, 00100 PinName rx, 00101 int baud, 00102 bool debug_on) 00103 { 00104 _apn = NULL; 00105 _uname = NULL; 00106 _pwd = NULL; 00107 _sim_pin_check_change_pending = false; 00108 _sim_pin_check_change_pending_enabled_value = false; 00109 _sim_pin_change_pending = false; 00110 _sim_pin_change_pending_new_pin_value = NULL; 00111 _ppp_connection_up = false; 00112 _connection_status_cb = NULL; 00113 00114 // Initialise the base class, which starts the AT parser` 00115 baseClassInit(tx, rx, baud, debug_on); 00116 } 00117 00118 // Destructor. 00119 UbloxPPPCellularInterface::~UbloxPPPCellularInterface() 00120 { 00121 if (_ppp_connection_up) { 00122 disconnect(); 00123 } 00124 } 00125 00126 // Set APN, user name and password. 00127 void UbloxPPPCellularInterface::set_credentials(const char *apn, 00128 const char *uname, 00129 const char *pwd) 00130 { 00131 _apn = apn; 00132 _uname = uname; 00133 _pwd = pwd; 00134 } 00135 00136 // Set PIN. 00137 void UbloxPPPCellularInterface::set_sim_pin(const char *pin) { 00138 set_pin(pin); 00139 } 00140 00141 // Make a cellular connection. 00142 nsapi_error_t UbloxPPPCellularInterface::connect(const char *sim_pin, 00143 const char *apn, 00144 const char *uname, 00145 const char *pwd) 00146 { 00147 nsapi_error_t nsapi_error; 00148 00149 if (sim_pin != NULL) { 00150 set_pin(sim_pin); 00151 } 00152 00153 if (apn != NULL) { 00154 _apn = apn; 00155 } 00156 00157 if ((uname != NULL) && (pwd != NULL)) { 00158 _uname = uname; 00159 _pwd = pwd; 00160 } else { 00161 _uname = NULL; 00162 _pwd = NULL; 00163 } 00164 00165 nsapi_error = connect(); 00166 00167 return nsapi_error; 00168 } 00169 00170 // Make a cellular connection 00171 nsapi_error_t UbloxPPPCellularInterface::connect() 00172 { 00173 nsapi_error_t nsapi_error = NSAPI_ERROR_IS_CONNECTED; 00174 const char * config = NULL; 00175 00176 if (!_ppp_connection_up) { 00177 00178 // Set up modem and then register with the network 00179 if (init()) { 00180 // Perform any pending SIM actions 00181 if (_sim_pin_check_change_pending) { 00182 if (!sim_pin_check_enable(_sim_pin_check_change_pending_enabled_value)) { 00183 nsapi_error = NSAPI_ERROR_AUTH_FAILURE; 00184 } 00185 _sim_pin_check_change_pending = false; 00186 } 00187 if (_sim_pin_change_pending) { 00188 if (!change_sim_pin(_sim_pin_change_pending_new_pin_value)) { 00189 nsapi_error = NSAPI_ERROR_AUTH_FAILURE; 00190 } 00191 _sim_pin_change_pending = false; 00192 } 00193 00194 if (nsapi_error != NSAPI_ERROR_AUTH_FAILURE) { 00195 nsapi_error = NSAPI_ERROR_NO_CONNECTION; 00196 for (int retries = 0; (nsapi_error == NSAPI_ERROR_NO_CONNECTION) && (retries < 3); retries++) { 00197 if (nwk_registration()) { 00198 nsapi_error = NSAPI_ERROR_OK; 00199 } 00200 } 00201 } 00202 } else { 00203 nsapi_error = NSAPI_ERROR_DEVICE_ERROR; 00204 } 00205 00206 if (nsapi_error == NSAPI_ERROR_OK) { 00207 // If the caller hasn't entered an APN, try to find it 00208 if (_apn == NULL) { 00209 config = apnconfig(_dev_info.imsi); 00210 } 00211 00212 // Attempt to connect 00213 do { 00214 // Set up APN and IP protocol for external PDP context 00215 get_next_credentials(&config); 00216 nsapi_error = setup_context_and_credentials(); 00217 00218 // Attempt to enter data mode 00219 if ((nsapi_error == NSAPI_ERROR_OK) && set_atd()) { 00220 wait_ms(1000); 00221 // Initialise PPP 00222 // nsapi_ppp_connect() is a blocking call, it will block until 00223 // connected, or timeout after 30 seconds 00224 nsapi_error = nsapi_ppp_connect(_fh, _connection_status_cb, _uname, _pwd); 00225 _ppp_connection_up = (nsapi_error == NSAPI_ERROR_OK); 00226 if (!_ppp_connection_up) { 00227 // If the connection has failed we may or may not still be 00228 // in data mode, depending on the nature of the failure, 00229 // so it's safest to force us back to command mode here 00230 // (if we're already in command mode the recv() call will 00231 // just time out) 00232 _at->send("~+++"); 00233 _at->recv("NO CARRIER"); 00234 } 00235 } 00236 } while (!_ppp_connection_up && config && *config); 00237 } 00238 00239 if (!_ppp_connection_up) { 00240 tr_error("Failed to connect, check your APN/username/password"); 00241 } 00242 } 00243 00244 return nsapi_error; 00245 } 00246 00247 // User initiated disconnect. 00248 nsapi_error_t UbloxPPPCellularInterface::disconnect() 00249 { 00250 nsapi_error_t nsapi_error = NSAPI_ERROR_DEVICE_ERROR; 00251 00252 if (nsapi_ppp_disconnect(_fh) == NSAPI_ERROR_OK) { 00253 _ppp_connection_up = false; 00254 // Get the "NO CARRIER" response out of the modem 00255 // so as not to confuse subsequent AT commands 00256 _at->send("AT") && _at->recv("NO CARRIER"); 00257 00258 if (nwk_deregistration()) { 00259 nsapi_error = NSAPI_ERROR_OK; 00260 } 00261 } 00262 00263 return nsapi_error; 00264 } 00265 00266 // Enable or disable SIM PIN check lock. 00267 nsapi_error_t UbloxPPPCellularInterface::set_sim_pin_check(bool set, 00268 bool immediate, 00269 const char *sim_pin) 00270 { 00271 nsapi_error_t nsapi_error = NSAPI_ERROR_AUTH_FAILURE; 00272 00273 if (sim_pin != NULL) { 00274 _pin = sim_pin; 00275 } 00276 00277 if (immediate) { 00278 if (init()) { 00279 if (sim_pin_check_enable(set)) { 00280 nsapi_error = NSAPI_ERROR_OK; 00281 } 00282 } else { 00283 nsapi_error = NSAPI_ERROR_DEVICE_ERROR; 00284 } 00285 } else { 00286 nsapi_error = NSAPI_ERROR_OK; 00287 _sim_pin_check_change_pending = true; 00288 _sim_pin_check_change_pending_enabled_value = set; 00289 } 00290 00291 return nsapi_error; 00292 } 00293 00294 // Change the PIN code for the SIM card. 00295 nsapi_error_t UbloxPPPCellularInterface::set_new_sim_pin(const char *new_pin, 00296 bool immediate, 00297 const char *old_pin) 00298 { 00299 nsapi_error_t nsapi_error = NSAPI_ERROR_AUTH_FAILURE; 00300 00301 if (old_pin != NULL) { 00302 _pin = old_pin; 00303 } 00304 00305 if (immediate) { 00306 if (init()) { 00307 if (change_sim_pin(new_pin)) { 00308 nsapi_error = NSAPI_ERROR_OK; 00309 } 00310 } else { 00311 nsapi_error = NSAPI_ERROR_DEVICE_ERROR; 00312 } 00313 } else { 00314 nsapi_error = NSAPI_ERROR_OK; 00315 _sim_pin_change_pending = true; 00316 _sim_pin_change_pending_new_pin_value = new_pin; 00317 } 00318 00319 return nsapi_error; 00320 } 00321 00322 // Determine if PPP is up. 00323 bool UbloxPPPCellularInterface::is_connected() 00324 { 00325 return _ppp_connection_up; 00326 } 00327 00328 // Get our IP address. 00329 const char *UbloxPPPCellularInterface::get_ip_address() 00330 { 00331 return nsapi_ppp_get_ip_addr(_fh); 00332 } 00333 00334 // Get the local network mask. 00335 const char *UbloxPPPCellularInterface::get_netmask() 00336 { 00337 return nsapi_ppp_get_netmask(_fh); 00338 } 00339 00340 // Get the local gateways. 00341 const char *UbloxPPPCellularInterface::get_gateway() 00342 { 00343 return nsapi_ppp_get_ip_addr(_fh); 00344 } 00345 00346 // Set the callback to be called in case the connection is lost. 00347 void UbloxPPPCellularInterface::connection_status_cb(Callback<void(nsapi_event_t, intptr_t)> cb) 00348 { 00349 _connection_status_cb = cb; 00350 } 00351 00352 #endif // NSAPI_PPP_AVAILABLE 00353 00354 // End of File 00355
Generated on Wed Jul 13 2022 20:24:27 by 1.7.2