Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers UBLOX_N2XX_CellularStack.cpp Source File

UBLOX_N2XX_CellularStack.cpp

00001 /*
00002  * Copyright (c) 2019, 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 "UBLOX_N2XX_CellularStack.h"
00019 #include "CellularUtil.h"
00020 #include <stdlib.h>
00021 
00022 using namespace mbed;
00023 using namespace mbed_cellular_util;
00024 
00025 UBLOX_N2XX_CellularStack::UBLOX_N2XX_CellularStack(ATHandler &atHandler, int cid, nsapi_ip_stack_t stack_type, AT_CellularDevice &device):
00026     AT_CellularStack(atHandler, cid, stack_type, device)
00027 {
00028     // URC handlers for sockets
00029     _at.set_urc_handler("+NSONMI:", callback(this, &UBLOX_N2XX_CellularStack::NSONMI_URC));
00030 }
00031 
00032 UBLOX_N2XX_CellularStack::~UBLOX_N2XX_CellularStack()
00033 {
00034     _at.set_urc_handler("+NSONMI:", NULL);
00035 }
00036 
00037 nsapi_error_t UBLOX_N2XX_CellularStack::socket_listen(nsapi_socket_t handle, int backlog)
00038 {
00039     return NSAPI_ERROR_UNSUPPORTED ;
00040 }
00041 
00042 nsapi_error_t UBLOX_N2XX_CellularStack::socket_accept(void *server, void **socket, SocketAddress *addr)
00043 {
00044     return NSAPI_ERROR_UNSUPPORTED ;
00045 }
00046 
00047 // Callback for Socket Read URC.
00048 void UBLOX_N2XX_CellularStack::NSONMI_URC()
00049 {
00050     int a, b;
00051     CellularSocket *socket;
00052 
00053     a = _at.read_int();
00054     b = _at.read_int();
00055 
00056     socket = find_socket(a);
00057     if (socket != NULL) {
00058         socket->pending_bytes = b;
00059         // No debug prints here as they can affect timing
00060         // and cause data loss in UARTSerial
00061         if (socket->_cb != NULL) {
00062             socket->_cb(socket->_data);
00063         }
00064     }
00065 }
00066 
00067 int UBLOX_N2XX_CellularStack::get_max_socket_count()
00068 {
00069     return N2XX_MAX_SOCKET;
00070 }
00071 
00072 bool UBLOX_N2XX_CellularStack::is_protocol_supported(nsapi_protocol_t protocol)
00073 {
00074     return (protocol == NSAPI_UDP );
00075 }
00076 
00077 nsapi_error_t UBLOX_N2XX_CellularStack::create_socket_impl(CellularSocket *socket)
00078 {
00079     int sock_id = -1;
00080     int localport = socket->localAddress.get_port();
00081 
00082     if (localport == 5683 || localport < 0 || localport > 65535) {
00083         return NSAPI_ERROR_NO_SOCKET ;
00084     }
00085 
00086     _at.lock();
00087     _at.cmd_start_stop("+NSOCR", "=", "%s%d%d%d", "DGRAM", 17, localport, 1);
00088 
00089     _at.resp_start();
00090     sock_id = _at.read_int();
00091     _at.resp_stop();
00092 
00093     if ((_at.get_last_error() != NSAPI_ERROR_OK ) || (sock_id == -1)) {
00094         _at.unlock();
00095         return NSAPI_ERROR_NO_SOCKET ;
00096     }
00097     _at.unlock();
00098 
00099     // Check for duplicate socket id delivered by modem
00100     for (int i = 0; i < N2XX_MAX_SOCKET; i++) {
00101         CellularSocket *sock = _socket[i];
00102         if (sock && sock != socket && sock->id == sock_id) {
00103             return NSAPI_ERROR_NO_SOCKET ;
00104         }
00105     }
00106 
00107     socket->started = true;
00108     socket->id = sock_id;
00109 
00110     return NSAPI_ERROR_OK ;
00111 }
00112 
00113 nsapi_size_or_error_t UBLOX_N2XX_CellularStack::socket_sendto_impl(CellularSocket *socket, const SocketAddress &address,
00114                                                                    const void *data, nsapi_size_t size)
00115 {
00116     MBED_ASSERT(socket->id != -1);
00117 
00118     if (size > N2XX_MAX_PACKET_SIZE) {
00119         return NSAPI_ERROR_PARAMETER ;
00120     }
00121 
00122     int sent_len = 0;
00123     char *dataStr = new char [(size * 2) + 1]();
00124     if (!dataStr) {
00125         return NSAPI_ERROR_NO_MEMORY ;
00126     }
00127     char_str_to_hex_str((const char *)data, size, dataStr);
00128 
00129     _at.cmd_start_stop("+NSOST", "=", "%d%s%d%d%s", socket->id, address.get_ip_address(),
00130                        address.get_port(), size, dataStr);
00131 
00132     _at.resp_start();
00133     _at.skip_param(); // skip socket id
00134     sent_len = _at.read_int();
00135     _at.resp_stop();
00136 
00137     delete[] dataStr;
00138     if ((_at.get_last_error() == NSAPI_ERROR_OK )) {
00139         return sent_len;
00140     }
00141 
00142     return _at.get_last_error();
00143 }
00144 
00145 nsapi_size_or_error_t UBLOX_N2XX_CellularStack::socket_recvfrom_impl(CellularSocket *socket, SocketAddress *address,
00146                                                                      void *buffer, nsapi_size_t size)
00147 {
00148     MBED_ASSERT(socket->id != -1);
00149 
00150     nsapi_size_or_error_t nsapi_error_size = NSAPI_ERROR_DEVICE_ERROR ;
00151     nsapi_size_t read_blk, usorf_sz, count = 0, length = size;
00152     bool success = true;
00153     char ipAddress[NSAPI_IP_SIZE];
00154     int port = 0;
00155     Timer timer;
00156 
00157     if (socket->pending_bytes == 0) {
00158         _at.process_oob();
00159         if (socket->pending_bytes == 0) {
00160             return NSAPI_ERROR_WOULD_BLOCK ;
00161         }
00162     }
00163 
00164     timer.start();
00165     while (success && (length > 0)) {
00166         read_blk = N2XX_MAX_PACKET_SIZE;
00167         if (read_blk > length) {
00168             read_blk = length;
00169         }
00170         if (socket->pending_bytes > 0) {
00171             _at.cmd_start_stop("+NSORF", "=", "%d%d", socket->id, read_blk);
00172 
00173             _at.resp_start();
00174             _at.skip_param(); // receiving socket id
00175             _at.read_string(ipAddress, sizeof(ipAddress));
00176             port = _at.read_int();
00177             usorf_sz = _at.read_int();
00178             if (usorf_sz > length) {
00179                 usorf_sz = length;
00180             }
00181             _at.read_hex_string((char *)buffer + count, usorf_sz);
00182             _at.resp_stop();
00183 
00184             // Must use what +NSORF returns here as it may be less or more than we asked for
00185             if (usorf_sz >= socket->pending_bytes) {
00186                 socket->pending_bytes = 0;
00187             } else {
00188                 socket->pending_bytes -= usorf_sz;
00189             }
00190 
00191             if (usorf_sz > 0) {
00192                 count += (usorf_sz);
00193                 length -= (usorf_sz);
00194             } else {
00195                 // read() should not fail
00196                 success = false;
00197             }
00198         }  else if (timer.read_ms() < SOCKET_TIMEOUT) {
00199             // Wait for URCs
00200             _at.process_oob();
00201         } else {
00202             if (count == 0) {
00203                 // Timeout with nothing received
00204                 nsapi_error_size = NSAPI_ERROR_WOULD_BLOCK ;
00205                 success = false;
00206             }
00207             length = 0; // This simply to cause an exit
00208         }
00209     }
00210     timer.stop();
00211 
00212     socket->pending_bytes = 0;
00213     if (!count || (_at.get_last_error() != NSAPI_ERROR_OK )) {
00214         return NSAPI_ERROR_WOULD_BLOCK ;
00215     }
00216 
00217     if (success && socket->proto == NSAPI_UDP  && address) {
00218         address->set_ip_address(ipAddress);
00219         address->get_ip_address();
00220         address->set_port(port);
00221     }
00222 
00223     return nsapi_error_size = count;
00224 }
00225 
00226 nsapi_error_t UBLOX_N2XX_CellularStack::socket_close_impl(int sock_id)
00227 {
00228     return _at.at_cmd_discard("+NSOCL", "=", "%d", sock_id);
00229 }