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