takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers AT_CellularStack.cpp Source File

AT_CellularStack.cpp

00001 /*
00002  * Copyright (c) 2017, 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 "AT_CellularStack.h"
00019 #include "CellularUtil.h"
00020 #include "CellularLog.h"
00021 
00022 using namespace mbed_cellular_util;
00023 using namespace mbed;
00024 
00025 AT_CellularStack::AT_CellularStack(ATHandler &at, int cid, nsapi_ip_stack_t stack_type) : AT_CellularBase(at), _socket(NULL), _socket_count(0), _cid(cid), _stack_type(stack_type)
00026 {
00027     memset(_ip, 0, PDP_IPV6_SIZE);
00028 }
00029 
00030 AT_CellularStack::~AT_CellularStack()
00031 {
00032     for (int i = 0; i < _socket_count; i++) {
00033         if (_socket[i]) {
00034             delete _socket[i];
00035             _socket[i] = NULL;
00036         }
00037     }
00038     _socket_count = 0;
00039 
00040     delete [] _socket;
00041     _socket = NULL;
00042 }
00043 
00044 /** NetworkStack
00045  */
00046 
00047 const char *AT_CellularStack::get_ip_address()
00048 {
00049     _at.lock();
00050 
00051     _at.cmd_start("AT+CGPADDR=");
00052     _at.write_int(_cid);
00053     _at.cmd_stop();
00054 
00055     _at.resp_start("+CGPADDR:");
00056 
00057     if (_at.info_resp()) {
00058 
00059         _at.skip_param();
00060 
00061         int len = _at.read_string(_ip, NSAPI_IPv4_SIZE - 1);
00062         if (len == -1) {
00063             _ip[0] = '\0';
00064             _at.resp_stop();
00065             _at.unlock();
00066             // no IPV4 address, return
00067             return NULL;
00068         }
00069 
00070         // in case stack type is not IPV4 only, try to look also for IPV6 address
00071         if (_stack_type != IPV4_STACK) {
00072             (void)_at.read_string(_ip, PDP_IPV6_SIZE - 1);
00073         }
00074     }
00075 
00076     _at.resp_stop();
00077     _at.unlock();
00078 
00079     // we have at least IPV4 address
00080     convert_ipv6(_ip);
00081 
00082     return _ip;
00083 }
00084 
00085 nsapi_error_t AT_CellularStack::socket_stack_init()
00086 {
00087     return NSAPI_ERROR_OK ;
00088 }
00089 
00090 nsapi_error_t AT_CellularStack::socket_open(nsapi_socket_t *handle, nsapi_protocol_t proto)
00091 {
00092     if (!is_protocol_supported(proto) || !handle) {
00093         return NSAPI_ERROR_UNSUPPORTED ;
00094     }
00095 
00096     int max_socket_count = get_max_socket_count();
00097 
00098     _socket_mutex.lock();
00099 
00100     if (!_socket) {
00101         if (socket_stack_init() != NSAPI_ERROR_OK ) {
00102             _socket_mutex.unlock();
00103             return NSAPI_ERROR_NO_SOCKET ;
00104         }
00105 
00106         _socket = new CellularSocket*[max_socket_count];
00107         if (!_socket) {
00108             tr_error("No memory to open socket!");
00109             _socket_mutex.unlock();
00110             return NSAPI_ERROR_NO_SOCKET ;
00111         }
00112         _socket_count = max_socket_count;
00113         for (int i = 0; i < max_socket_count; i++) {
00114             _socket[i] = 0;
00115         }
00116     }
00117 
00118     int index = -1;
00119     for (int i = 0; i < max_socket_count; i++) {
00120         if (!_socket[i]) {
00121             index = i;
00122             break;
00123         }
00124     }
00125 
00126     if (index == -1) {
00127         tr_error("No socket found!");
00128         _socket_mutex.unlock();
00129         return NSAPI_ERROR_NO_SOCKET ;
00130     }
00131 
00132     tr_info("Socket open index: %d", index);
00133     // create local socket structure, socket on modem is created when app calls sendto/recvfrom
00134     _socket[index] = new CellularSocket;
00135     CellularSocket *psock;
00136     psock = _socket[index];
00137     memset(psock, 0, sizeof(CellularSocket));
00138     SocketAddress addr(0, get_dynamic_ip_port());
00139     psock->id = index;
00140     psock->localAddress = addr;
00141     psock->proto = proto;
00142     *handle = psock;
00143 
00144     _socket_mutex.unlock();
00145 
00146     return NSAPI_ERROR_OK ;
00147 }
00148 
00149 nsapi_error_t AT_CellularStack::socket_close(nsapi_socket_t handle)
00150 {
00151     int err = NSAPI_ERROR_DEVICE_ERROR ;
00152 
00153     struct CellularSocket *socket = (struct CellularSocket *)handle;
00154     if (!socket) {
00155         return err;
00156     }
00157     int sock_id = socket->id;
00158     bool sock_created = socket->created;
00159     int max_socket_count = get_max_socket_count();
00160 
00161     int index = -1;
00162     for (int i = 0; i < max_socket_count; i++) {
00163         if (_socket[i] == socket) {
00164             index = i;
00165             break;
00166         }
00167     }
00168 
00169     tr_info("Close socket index: %d id: %d created: %d", index, sock_id, socket->created);
00170 
00171     if (index == -1) {
00172         tr_error("No socket found to be closed");
00173         return err;
00174     }
00175 
00176     err = NSAPI_ERROR_OK ;
00177 
00178     // Close the socket on the modem if it was created
00179     _at.lock();
00180     if (sock_created) {
00181         err = socket_close_impl(sock_id);
00182     }
00183 
00184     _socket[index] = NULL;
00185     delete socket;
00186 
00187     _at.unlock();
00188 
00189     return err;
00190 }
00191 
00192 nsapi_error_t AT_CellularStack::socket_bind(nsapi_socket_t handle, const SocketAddress &addr)
00193 {
00194     struct CellularSocket *socket = (CellularSocket *)handle;
00195     if (!socket) {
00196         return NSAPI_ERROR_DEVICE_ERROR ;
00197     }
00198 
00199     if (addr) {
00200         socket->localAddress.set_addr(addr.get_addr());
00201     }
00202 
00203     if (addr.get_port()) {
00204         socket->localAddress.set_port(addr.get_port());
00205     }
00206 
00207     _at.lock();
00208 
00209     if (!socket->created) {
00210         create_socket_impl(socket);
00211     }
00212 
00213     return _at.unlock_return_error();
00214 }
00215 
00216 nsapi_error_t AT_CellularStack::socket_listen(nsapi_socket_t handle, int backlog)
00217 {
00218     return NSAPI_ERROR_UNSUPPORTED ;;
00219 }
00220 
00221 nsapi_error_t AT_CellularStack::socket_connect(nsapi_socket_t handle, const SocketAddress &addr)
00222 {
00223     CellularSocket *socket = (CellularSocket *)handle;
00224     if (!socket) {
00225         return NSAPI_ERROR_DEVICE_ERROR ;
00226     }
00227     socket->remoteAddress = addr;
00228     socket->connected = true;
00229 
00230     return NSAPI_ERROR_OK ;
00231 }
00232 
00233 nsapi_error_t AT_CellularStack::socket_accept(void *server, void **socket, SocketAddress *addr)
00234 {
00235     return NSAPI_ERROR_UNSUPPORTED ;;
00236 }
00237 
00238 nsapi_size_or_error_t AT_CellularStack::socket_send(nsapi_socket_t handle, const void *data, unsigned size)
00239 {
00240     CellularSocket *socket = (CellularSocket *)handle;
00241     if (!socket || !socket->connected) {
00242         return NSAPI_ERROR_DEVICE_ERROR ;
00243     }
00244     return socket_sendto(handle, socket->remoteAddress, data, size);
00245 }
00246 
00247 nsapi_size_or_error_t AT_CellularStack::socket_sendto(nsapi_socket_t handle, const SocketAddress &addr, const void *data, unsigned size)
00248 {
00249     CellularSocket *socket = (CellularSocket *)handle;
00250     if (!socket) {
00251         return NSAPI_ERROR_DEVICE_ERROR ;
00252     }
00253 
00254     nsapi_size_or_error_t ret_val = NSAPI_ERROR_OK ;
00255 
00256     if (!socket->created) {
00257         _at.lock();
00258 
00259         ret_val = create_socket_impl(socket);
00260 
00261         _at.unlock();
00262         if (ret_val != NSAPI_ERROR_OK ) {
00263             tr_error("Error creating socket to send to: %s error code: %d", addr.get_ip_address(), ret_val);
00264             return ret_val;
00265         } else {
00266             tr_info("Success creating socket to send to: %s", addr.get_ip_address());
00267         }
00268     }
00269 
00270     /* Check parameters */
00271     if (addr.get_ip_version() == NSAPI_UNSPEC ) {
00272         return NSAPI_ERROR_DEVICE_ERROR ;
00273     }
00274 
00275     _at.lock();
00276 
00277     ret_val = socket_sendto_impl(socket, addr, data, size);
00278 
00279     if (ret_val > 0) {
00280         tr_info("Success sending %d Bytes to: %s", ret_val, addr.get_ip_address());
00281     } else if (ret_val != NSAPI_ERROR_WOULD_BLOCK ) {
00282         tr_error("Error sending to: %s error code: %d", addr.get_ip_address(), ret_val);
00283     }
00284 
00285     _at.unlock();
00286 
00287     return ret_val;
00288 }
00289 
00290 nsapi_size_or_error_t AT_CellularStack::socket_recv(nsapi_socket_t handle, void *data, unsigned size)
00291 {
00292     return socket_recvfrom(handle, NULL, data, size);
00293 }
00294 
00295 nsapi_size_or_error_t AT_CellularStack::socket_recvfrom(nsapi_socket_t handle, SocketAddress *addr, void *buffer, unsigned size)
00296 {
00297     CellularSocket *socket = (CellularSocket *)handle;
00298     if (!socket) {
00299         return NSAPI_ERROR_DEVICE_ERROR ;
00300     }
00301 
00302     nsapi_size_or_error_t ret_val = NSAPI_ERROR_OK ;
00303 
00304     if (!socket->created) {
00305         _at.lock();
00306 
00307         ret_val = create_socket_impl(socket);
00308 
00309         _at.unlock();
00310         if (ret_val != NSAPI_ERROR_OK ) {
00311             return ret_val;
00312         }
00313     }
00314 
00315     _at.lock();
00316 
00317     ret_val = socket_recvfrom_impl(socket, addr, buffer, size);
00318 
00319     _at.unlock();
00320 
00321     return ret_val;
00322 }
00323 
00324 void AT_CellularStack::socket_attach(nsapi_socket_t handle, void (*callback)(void *), void *data)
00325 {
00326     CellularSocket *socket = (CellularSocket *)handle;
00327     if (!socket) {
00328         return;
00329     }
00330     socket->_cb = callback;
00331     socket->_data = data;
00332 }