Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers GEMALTO_CINTERION_CellularStack.cpp Source File

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 }