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
GEMALTO_CINTERION_CellularStack.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 00018 #include <cstdlib> 00019 #include "GEMALTO_CINTERION_CellularStack.h" 00020 #include "GEMALTO_CINTERION.h" 00021 #include "CellularLog.h" 00022 00023 // defines as per ELS61-E2_ATC_V01.000 and BGS2-W_ATC_V00.100 00024 #define SOCKET_MAX 10 00025 #define UDP_PACKET_SIZE 1460 00026 #define FAILURE_TIMEOUT (30*1000) // failure timeout in milliseconds on modem side 00027 00028 using namespace mbed; 00029 00030 GEMALTO_CINTERION_CellularStack::GEMALTO_CINTERION_CellularStack(ATHandler &atHandler, const char *apn, const char *user, const char *password, 00031 int cid, nsapi_ip_stack_t stack_type, AT_CellularDevice &device) : 00032 AT_CellularStack(atHandler, cid, stack_type, device), _apn(apn), _user(user), _password(password) 00033 { 00034 } 00035 00036 GEMALTO_CINTERION_CellularStack::~GEMALTO_CINTERION_CellularStack() 00037 { 00038 _at.set_urc_handler("^SIS:", 0); 00039 _at.set_urc_handler("^SISW:", 0); 00040 _at.set_urc_handler("^SISR:", 0); 00041 } 00042 00043 void GEMALTO_CINTERION_CellularStack::urc_sis() 00044 { 00045 int sock_id = _at.read_int(); 00046 int urc_code = _at.read_int(); 00047 CellularSocket *sock = find_socket(sock_id); 00048 if (sock) { 00049 // Currently only UDP is supported so there is need to handle only some error codes here, 00050 // and others are detected on sendto/recvfrom responses. 00051 if (urc_code == 5) { // The service is ready to use (ELS61 and EMS31). 00052 if (sock->_cb) { 00053 sock->started = true; 00054 sock->tx_ready = true; 00055 sock->_cb(sock->_data); 00056 } 00057 } 00058 if (urc_code == 0) { 00059 int urc_info_id = _at.read_int(); 00060 if (urc_info_id == 48) { 00061 tr_info("Socket closed %d", sock_id); 00062 sock->closed = true; 00063 if (sock->_cb) { 00064 sock->_cb(sock->_data); 00065 } 00066 00067 } 00068 } 00069 } 00070 } 00071 00072 void GEMALTO_CINTERION_CellularStack::urc_sisw() 00073 { 00074 int sock_id = _at.read_int(); 00075 int urc_code = _at.read_int(); 00076 sisw_urc_handler(sock_id, urc_code); 00077 } 00078 00079 void GEMALTO_CINTERION_CellularStack::sisw_urc_handler(int sock_id, int urc_code) 00080 { 00081 CellularSocket *sock = find_socket(sock_id); 00082 if (sock) { 00083 if (urc_code == 1) { // ready 00084 if (sock->_cb) { 00085 sock->tx_ready = true; 00086 if (sock->proto == NSAPI_TCP || GEMALTO_CINTERION::get_module() == GEMALTO_CINTERION::ModuleBGS2) { 00087 sock->started = true; 00088 } 00089 sock->_cb(sock->_data); 00090 } 00091 } 00092 } 00093 } 00094 00095 void GEMALTO_CINTERION_CellularStack::urc_sisr() 00096 { 00097 int sock_id = _at.read_int(); 00098 int urc_code = _at.read_int(); 00099 sisr_urc_handler(sock_id, urc_code); 00100 } 00101 00102 void GEMALTO_CINTERION_CellularStack::sisr_urc_handler(int sock_id, int urc_code) 00103 { 00104 CellularSocket *sock = find_socket(sock_id); 00105 if (sock) { 00106 if (urc_code == 1) { // data available 00107 if (sock->_cb) { 00108 sock->pending_bytes = 1; 00109 sock->_cb(sock->_data); 00110 } 00111 } 00112 } 00113 } 00114 00115 nsapi_error_t GEMALTO_CINTERION_CellularStack::socket_stack_init() 00116 { 00117 _at.lock(); 00118 nsapi_error_t err = create_connection_profile(_cid); 00119 if (!err) { 00120 _at.set_urc_handler("^SIS:", mbed::Callback<void()>(this, &GEMALTO_CINTERION_CellularStack::urc_sis)); 00121 _at.set_urc_handler("^SISW:", mbed::Callback<void()>(this, &GEMALTO_CINTERION_CellularStack::urc_sisw)); 00122 _at.set_urc_handler("^SISR:", mbed::Callback<void()>(this, &GEMALTO_CINTERION_CellularStack::urc_sisr)); 00123 } else { // recovery cleanup 00124 // close all Internet and connection profiles 00125 for (int i = 0; i < SOCKET_MAX; i++) { 00126 _at.clear_error(); 00127 socket_close_impl(i); 00128 } 00129 _at.clear_error(); 00130 close_connection_profile(_cid); 00131 } 00132 _at.unlock(); 00133 return err; 00134 } 00135 00136 int GEMALTO_CINTERION_CellularStack::get_max_socket_count() 00137 { 00138 return SOCKET_MAX; 00139 } 00140 00141 bool GEMALTO_CINTERION_CellularStack::is_protocol_supported(nsapi_protocol_t protocol) 00142 { 00143 return (protocol == NSAPI_UDP || protocol == NSAPI_TCP ); 00144 } 00145 00146 nsapi_error_t GEMALTO_CINTERION_CellularStack::socket_close_impl(int sock_id) 00147 { 00148 tr_debug("Cinterion close %d", sock_id); 00149 00150 _at.set_at_timeout(FAILURE_TIMEOUT); 00151 00152 _at.at_cmd_discard("^SISC", "=", "%d", sock_id); 00153 00154 _at.clear_error(); // clear SISS even though SISC fails 00155 00156 _at.at_cmd_discard("^SISS", "=", "%d%s%s", sock_id, "srvType", "none"); 00157 00158 _at.restore_at_timeout(); 00159 00160 return _at.get_last_error(); 00161 } 00162 00163 nsapi_error_t GEMALTO_CINTERION_CellularStack::socket_open_defer(CellularSocket *socket, const SocketAddress *address) 00164 { 00165 int retry_open = 1; 00166 retry_open: 00167 // setup internet session profile 00168 int internet_service_id = find_socket_index(socket); 00169 bool foundSrvType = false; 00170 bool foundConIdType = false; 00171 _at.cmd_start_stop("^SISS", "?"); 00172 _at.resp_start("^SISS:"); 00173 /* 00174 * Profile is a list of tag-value map: 00175 * ^SISS: <srvProfileId>, <srvParmTag>, <srvParmValue> 00176 * [^SISS: ...] 00177 */ 00178 while (_at.info_resp()) { 00179 int id = _at.read_int(); 00180 if (id == internet_service_id) { 00181 char paramTag[16]; 00182 int paramTagLen = _at.read_string(paramTag, sizeof(paramTag)); 00183 if (paramTagLen > 0) { 00184 char paramValue[100 + 1]; // APN may be up to 100 chars 00185 int paramValueLen = _at.read_string(paramValue, sizeof(paramValue)); 00186 if (paramValueLen >= 0) { 00187 if (strcmp(paramTag, "srvType") == 0) { 00188 if (strcmp(paramValue, "Socket") == 0) { 00189 foundSrvType = true; 00190 } 00191 } 00192 if (strcmp(paramTag, "address") == 0) { 00193 if (strncmp(paramValue, "sock", sizeof("sock")) == 0) { 00194 foundSrvType = true; 00195 } 00196 } 00197 if (strcmp(paramTag, "conId") == 0) { 00198 char buf[10]; 00199 std::sprintf(buf, "%d", _cid); 00200 if (strcmp(paramValue, buf) == 0) { 00201 foundConIdType = true; 00202 } 00203 } 00204 } 00205 } 00206 } 00207 } 00208 _at.resp_stop(); 00209 00210 if (!foundSrvType) { 00211 _at.at_cmd_discard("^SISS", "=", "%d%s%s", internet_service_id, "srvType", "Socket"); 00212 } 00213 00214 if (!foundConIdType) { 00215 _at.at_cmd_discard("^SISS", "=", "%d%s%d", internet_service_id, "conId", _cid); 00216 } 00217 00218 // host address (IPv4) and local+remote port is needed only for BGS2 which does not support UDP server socket 00219 char sock_addr[sizeof("sockudp://") - 1 + NSAPI_IPv6_SIZE + sizeof("[]:12345;port=12345") - 1 + 1]; 00220 00221 if (socket->proto == NSAPI_UDP ) { 00222 if (GEMALTO_CINTERION::get_module() != GEMALTO_CINTERION::ModuleBGS2) { 00223 std::sprintf(sock_addr, "sockudp://%s:%u", address ? address->get_ip_address() : "", socket->localAddress.get_port()); 00224 } else { 00225 std::sprintf(sock_addr, "sockudp://%s:%u;port=%u", address->get_ip_address(), address->get_port(), socket->localAddress.get_port()); 00226 } 00227 } else { 00228 if (address->get_ip_version() == NSAPI_IPv4 ) { 00229 std::sprintf(sock_addr, "socktcp://%s:%u", address->get_ip_address(), address->get_port()); 00230 } else { 00231 std::sprintf(sock_addr, "socktcp://[%s]:%u", address->get_ip_address(), address->get_port()); 00232 } 00233 } 00234 00235 _at.cmd_start("AT^SISS="); 00236 _at.write_int(internet_service_id); 00237 _at.write_string("address", false); 00238 _at.write_string(sock_addr); 00239 _at.cmd_stop_read_resp(); 00240 00241 _at.at_cmd_discard("^SISO", "=", "%d", internet_service_id); 00242 00243 if (_at.get_last_error()) { 00244 tr_error("Socket %d open failed!", internet_service_id); 00245 _at.clear_error(); 00246 socket_close_impl(internet_service_id); // socket may already be open on modem if app and modem are not in sync, as a recovery, try to close the socket so open succeeds the next time 00247 if (retry_open--) { 00248 goto retry_open; 00249 } 00250 return NSAPI_ERROR_NO_SOCKET ; 00251 } 00252 00253 socket->id = internet_service_id; 00254 tr_debug("Cinterion open %d (err %d)", socket->id, _at.get_last_error()); 00255 00256 return _at.get_last_error(); 00257 } 00258 00259 // To open socket: 00260 // 1. Select URC mode or polling mode with AT^SCFG 00261 // 2. create a GPRS connection profile with AT^SICS (must have PDP) 00262 // 3. create service profile with AT^SISS and map connectionID to serviceID 00263 // 4. open internet session with AT^SISO (ELS61 tries to attach to a packet domain) 00264 nsapi_error_t GEMALTO_CINTERION_CellularStack::create_socket_impl(CellularSocket *socket) 00265 { 00266 if (socket->proto == NSAPI_UDP ) { 00267 if (GEMALTO_CINTERION::get_module() != GEMALTO_CINTERION::ModuleBGS2) { 00268 return socket_open_defer(socket); 00269 } 00270 } 00271 00272 return _at.get_last_error(); 00273 } 00274 00275 nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_sendto_impl(CellularSocket *socket, 00276 const SocketAddress &address, const void *data, nsapi_size_t size) 00277 { 00278 if (socket->proto == NSAPI_UDP ) { 00279 const int ip_version = address.get_ip_version(); 00280 if (_stack_type != IPV4V6_STACK && 00281 ((ip_version == NSAPI_IPv4 && _stack_type != IPV4_STACK) || 00282 (ip_version == NSAPI_IPv6 && _stack_type != IPV6_STACK))) { 00283 tr_warn("No IP route for %s", address.get_ip_address()); 00284 return NSAPI_ERROR_NO_SOCKET ; 00285 } 00286 } 00287 00288 if (socket->proto == NSAPI_UDP && GEMALTO_CINTERION::get_module() == GEMALTO_CINTERION::ModuleBGS2) { 00289 tr_debug("Send addr %s, prev addr %s", address.get_ip_address(), socket->remoteAddress.get_ip_address()); 00290 if (address != socket->remoteAddress) { 00291 if (socket->started) { 00292 socket_close_impl(socket->id); 00293 _at.clear_error(); 00294 } 00295 00296 if (create_socket_impl(socket) != NSAPI_ERROR_OK ) { 00297 tr_error("Failed to create socket %d", socket->id); 00298 return NSAPI_ERROR_NO_SOCKET ; 00299 } 00300 if (socket_open_defer(socket, &address) != NSAPI_ERROR_OK ) { 00301 tr_error("Failed to open socket %d", socket->id); 00302 return NSAPI_ERROR_NO_SOCKET ; 00303 } 00304 socket->remoteAddress = address; 00305 _at.resp_start("^SISW:"); 00306 int sock_id = _at.read_int(); 00307 MBED_ASSERT(sock_id == socket->id); 00308 int urc_code = _at.read_int(); 00309 tr_debug("TX ready: socket=%d, urc=%d (err=%d)", sock_id, urc_code, _at.get_last_error()); 00310 (void)sock_id; 00311 (void)urc_code; 00312 socket->started = true; 00313 socket->tx_ready = true; 00314 } 00315 } 00316 if (!socket->started || !socket->tx_ready) { 00317 tr_debug("Socket %d send would block (started %d, tx %d)", socket->id, socket->started, socket->tx_ready); 00318 return NSAPI_ERROR_WOULD_BLOCK ; 00319 } 00320 00321 if (size > UDP_PACKET_SIZE) { 00322 tr_error("sendto size %d (max %d)", size, UDP_PACKET_SIZE); 00323 return NSAPI_ERROR_PARAMETER ; 00324 } 00325 00326 _at.set_at_timeout(FAILURE_TIMEOUT); 00327 00328 if (GEMALTO_CINTERION::get_module() != GEMALTO_CINTERION::ModuleBGS2) { 00329 // UDP requires Udp_RemClient 00330 if (socket->proto == NSAPI_UDP ) { 00331 char socket_address[NSAPI_IPv6_SIZE + sizeof("[]:12345") - 1 + 1]; 00332 if (address.get_ip_version() == NSAPI_IPv4 ) { 00333 std::sprintf(socket_address, "%s:%u", address.get_ip_address(), address.get_port()); 00334 } else { 00335 std::sprintf(socket_address, "[%s]:%u", address.get_ip_address(), address.get_port()); 00336 } 00337 _at.cmd_start_stop("^SISW", "=", "%d%d%d%s", socket->id, size, 0, socket_address); 00338 } else { 00339 _at.cmd_start_stop("^SISW", "=", "%d%d%d", socket->id, size, 0); 00340 } 00341 } else { 00342 _at.cmd_start_stop("^SISW", "=", "%d%d", socket->id, size); 00343 } 00344 00345 sisw_retry: 00346 _at.resp_start("^SISW:"); 00347 if (!_at.info_resp()) { 00348 tr_error("Socket %d send failure", socket->id); 00349 _at.restore_at_timeout(); 00350 return NSAPI_ERROR_DEVICE_ERROR ; 00351 } 00352 int socket_id = _at.read_int(); 00353 if (socket_id != socket->id) { 00354 // We might have read the SISW URC so let's try to handle it 00355 const int urc_code = _at.read_int(); 00356 const int extra = _at.read_int(); 00357 if (urc_code != -1 && extra == -1) { 00358 sisw_urc_handler(socket_id, urc_code); 00359 goto sisw_retry; 00360 } 00361 _at.restore_at_timeout(); 00362 tr_error("Socket id %d != %d", socket_id, socket->id); 00363 return NSAPI_ERROR_DEVICE_ERROR ; 00364 } 00365 int accept_len = _at.read_int(); 00366 if (accept_len == -1) { 00367 tr_error("Socket %d send failed", socket->id); 00368 _at.restore_at_timeout(); 00369 return NSAPI_ERROR_DEVICE_ERROR ; 00370 } 00371 _at.skip_param(); // unackData 00372 00373 _at.write_bytes((uint8_t *)data, accept_len); 00374 _at.resp_stop(); 00375 _at.restore_at_timeout(); 00376 00377 if (_at.get_last_error() == NSAPI_ERROR_OK ) { 00378 socket->tx_ready = false; 00379 } 00380 00381 return (_at.get_last_error() == NSAPI_ERROR_OK ) ? accept_len : NSAPI_ERROR_DEVICE_ERROR ; 00382 } 00383 00384 nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_recvfrom_impl(CellularSocket *socket, SocketAddress *address, 00385 void *buffer, nsapi_size_t size) 00386 { 00387 // AT_CellularStack::recvfrom(...) will make sure that we do have a socket 00388 // open on the modem, assert here to catch a programming error 00389 MBED_ASSERT(socket->id != -1); 00390 00391 // we must use this flag, otherwise ^SISR URC can come while we are reading response and there is 00392 // no way to detect if that is really an URC or response 00393 if (!socket->pending_bytes) { 00394 _at.process_oob(); // check for ^SISR URC 00395 if (!socket->pending_bytes) { 00396 tr_debug("Socket %d recv would block", socket->id); 00397 return NSAPI_ERROR_WOULD_BLOCK ; 00398 } 00399 } 00400 00401 if (size > UDP_PACKET_SIZE) { 00402 size = UDP_PACKET_SIZE; 00403 } 00404 00405 _at.cmd_start_stop("^SISR", "=", "%d%d", socket->id, size); 00406 00407 sisr_retry: 00408 _at.resp_start("^SISR:"); 00409 if (!_at.info_resp()) { 00410 tr_error("Socket %d not responding", socket->id); 00411 return NSAPI_ERROR_DEVICE_ERROR ; 00412 } 00413 00414 int socket_id = _at.read_int(); 00415 if (socket_id != socket->id) { 00416 const int urc_code = _at.read_int(); 00417 const int extra = _at.read_int(); // should be -1 if URC 00418 if (urc_code != -1 && extra == -1) { 00419 sisr_urc_handler(socket_id, urc_code); 00420 goto sisr_retry; 00421 } 00422 tr_error("Socket recvfrom id %d != %d", socket_id, socket->id); 00423 return NSAPI_ERROR_DEVICE_ERROR ; 00424 } 00425 00426 nsapi_size_or_error_t len = _at.read_int(); 00427 if (len == 0) { 00428 tr_warn("Socket %d no data", socket->id); 00429 _at.resp_stop(); 00430 return NSAPI_ERROR_WOULD_BLOCK ; 00431 } 00432 if (len == -1) { 00433 tr_error("Socket %d recvfrom failed!", socket->id); 00434 return NSAPI_ERROR_DEVICE_ERROR ; 00435 } 00436 socket->pending_bytes = 0; 00437 if (len >= (nsapi_size_or_error_t)size) { 00438 len = (nsapi_size_or_error_t)size; 00439 int remain_len = _at.read_int(); 00440 if (remain_len > 0) { 00441 socket->pending_bytes = 1; 00442 } 00443 } 00444 00445 // UDP Udp_RemClient 00446 if (socket->proto == NSAPI_UDP && GEMALTO_CINTERION::get_module() != GEMALTO_CINTERION::ModuleBGS2) { 00447 char ip_address[NSAPI_IPv6_SIZE + sizeof("[]:12345") - 1 + 1]; 00448 int ip_len = _at.read_string(ip_address, sizeof(ip_address)); 00449 if (ip_len <= 0) { 00450 tr_error("Socket %d recvfrom addr (len %d)", socket->id, ip_len); 00451 return NSAPI_ERROR_DEVICE_ERROR ; 00452 } 00453 if (address) { 00454 char *ip_start = ip_address; 00455 char *ip_stop; 00456 char *port_start; 00457 if (_stack_type == IPV6_STACK) { 00458 ip_start++; // skip '[' 00459 ip_stop = strchr(ip_address, ']'); 00460 if (ip_stop) { 00461 port_start = strchr(ip_stop, ':'); 00462 } 00463 } else { 00464 ip_stop = strchr(ip_address, ':'); 00465 port_start = ip_stop; 00466 } 00467 if (ip_stop && port_start) { 00468 char tmp_ch = *ip_stop; 00469 *ip_stop = '\0'; // split IP and port 00470 address->set_ip_address(ip_start); 00471 port_start++; // skip ':' 00472 int port = std::strtol(port_start, NULL, 10); 00473 address->set_port(port); 00474 *ip_stop = tmp_ch; // restore original IP string 00475 } 00476 } 00477 } else { 00478 if (address) { 00479 *address = socket->remoteAddress; 00480 } 00481 } 00482 00483 nsapi_size_or_error_t recv_len = _at.read_bytes((uint8_t *)buffer, len); 00484 00485 _at.resp_stop(); 00486 00487 return (_at.get_last_error() == NSAPI_ERROR_OK ) ? (recv_len ? recv_len : NSAPI_ERROR_WOULD_BLOCK ) : NSAPI_ERROR_DEVICE_ERROR ; 00488 } 00489 00490 // setup internet connection profile for sockets 00491 nsapi_error_t GEMALTO_CINTERION_CellularStack::create_connection_profile(int connection_profile_id) 00492 { 00493 if (GEMALTO_CINTERION::get_module() == GEMALTO_CINTERION::ModuleEMS31) { 00494 // EMS31 connection has only DNS settings and there is no need to modify those here for now 00495 return NSAPI_ERROR_OK ; 00496 } 00497 00498 char conParamType[sizeof("GPRS0") + 1]; 00499 std::sprintf(conParamType, "GPRS%d", (_stack_type == IPV4_STACK) ? 0 : 6); 00500 00501 _at.cmd_start_stop("^SICS", "?"); 00502 bool found_connection = false; 00503 _at.resp_start("^SICS:"); 00504 while (_at.info_resp()) { 00505 int id = _at.read_int(); 00506 if (id == connection_profile_id) { 00507 char paramTag[16]; 00508 int paramTagLen = _at.read_string(paramTag, sizeof(paramTag)); 00509 if (paramTagLen > 0) { 00510 char paramValue[100 + 1]; // APN may be up to 100 chars 00511 int paramValueLen = _at.read_string(paramValue, sizeof(paramValue)); 00512 if (paramValueLen >= 0) { 00513 if (strcmp(paramTag, "conType") == 0) { 00514 if (strcmp(paramValue, conParamType) == 0) { 00515 found_connection = true; 00516 break; 00517 } 00518 } 00519 } 00520 } 00521 } 00522 } 00523 _at.resp_stop(); 00524 00525 // connection profile is bound to a PDP context and it can not be changed 00526 if (!found_connection) { 00527 _at.at_cmd_discard("^SICS", "=", "%d%s%s", connection_profile_id, "conType", conParamType); 00528 00529 if (_apn && strlen(_apn) > 0) { 00530 _at.at_cmd_discard("^SICS", "=", "%d%s%s", connection_profile_id, "apn", _apn); 00531 } 00532 00533 if (_user && strlen(_user) > 0) { 00534 _at.at_cmd_discard("^SICS", "=", "%d%s%s", connection_profile_id, "user", _user); 00535 } 00536 00537 if (_password && strlen(_password) > 0) { 00538 _at.at_cmd_discard("^SICS", "=", "%d%s%s", connection_profile_id, "passwd", _password); 00539 } 00540 00541 // set maximum inactivity timeout 00542 _at.at_cmd_discard("^SICS", "=", "%d%s%d", connection_profile_id, "inactTO", 0xffff); 00543 00544 // use URC mode ON 00545 _at.at_cmd_discard("^SCFG", "=", "%s%s", "Tcp/withURCs", "on"); 00546 } 00547 00548 tr_debug("Cinterion profile %d, %s (err %d)", connection_profile_id, (_stack_type == IPV4_STACK) ? "IPv4" : "IPv6", _at.get_last_error()); 00549 return _at.get_last_error(); 00550 } 00551 00552 void GEMALTO_CINTERION_CellularStack::close_connection_profile(int connection_profile_id) 00553 { 00554 if (GEMALTO_CINTERION::get_module() == GEMALTO_CINTERION::ModuleEMS31) { 00555 return; 00556 } 00557 00558 // To clear connection profile need to detach from packet data. 00559 // After detach modem sends PDP disconnected event to network class, 00560 // which propagates network disconnected to upper layer to start reconnecting. 00561 _at.at_cmd_discard("+CGATT", "=0"); 00562 _at.clear_error(); 00563 00564 _at.at_cmd_discard("^SICS", "=", "%d%s%s", connection_profile_id, "conType", "none"); 00565 00566 _at.clear_error(); 00567 } 00568 00569 nsapi_error_t GEMALTO_CINTERION_CellularStack::socket_connect(nsapi_socket_t handle, const SocketAddress &address) 00570 { 00571 int err = NSAPI_ERROR_DEVICE_ERROR ; 00572 00573 struct CellularSocket *socket = (struct CellularSocket *)handle; 00574 if (!socket) { 00575 return err; 00576 } 00577 00578 _at.lock(); 00579 err = create_socket_impl(socket); 00580 if (err != NSAPI_ERROR_OK ) { 00581 _at.unlock(); 00582 return err; 00583 } 00584 err = socket_open_defer(socket, &address); 00585 _at.unlock(); 00586 00587 if (err == NSAPI_ERROR_OK ) { 00588 socket->remoteAddress = address; 00589 socket->connected = true; 00590 } 00591 00592 return err; 00593 }
Generated on Tue Jul 12 2022 13:54:23 by
