Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers RM1000_AT_CellularStack.cpp Source File

RM1000_AT_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 "RM1000_AT_CellularStack.h"
00019 
00020 #include "mbed_poll.h"
00021 
00022 #include "mbed-trace/mbed_trace.h"
00023 #ifndef TRACE_GROUP
00024 #define TRACE_GROUP  "RIOT"
00025 #endif // TRACE_GROUP
00026 
00027 using namespace mbed;
00028 using namespace mbed_cellular_util;
00029 
00030 RM1000_AT_CellularStack::RM1000_AT_CellularStack(ATHandler &atHandler, int cid, nsapi_ip_stack_t stack_type, AT_CellularDevice &device) :
00031     AT_CellularStack(atHandler, cid, stack_type, device)
00032 {
00033     tr_debug("RM1000_AT_CellularStack::RM1000_AT_CellularStack");
00034 
00035     // URC handlers for sockets
00036     _at.set_urc_handler("+RUSORCV:", callback(this, &RM1000_AT_CellularStack::RUSORCV_URC));
00037     _at.set_urc_handler("+RUSOCL:", callback(this, &RM1000_AT_CellularStack::RUSOCL_URC));
00038 }
00039 
00040 RM1000_AT_CellularStack::~RM1000_AT_CellularStack()
00041 {
00042     tr_debug("RM1000_AT_CellularStack::~RM1000_AT_CellularStack");
00043 
00044     _at.set_urc_handler("+RUSORCV:", NULL);
00045     _at.set_urc_handler("+RUSOCL:", NULL);
00046 }
00047 
00048 nsapi_error_t RM1000_AT_CellularStack::socket_listen(nsapi_socket_t handle, int backlog)
00049 {
00050     tr_debug("RM1000_AT_CellularStack::socket_listen");
00051     return NSAPI_ERROR_UNSUPPORTED ;
00052 }
00053 
00054 nsapi_error_t RM1000_AT_CellularStack::socket_accept(void *server, void **socket, SocketAddress *addr)
00055 {
00056     tr_debug("RM1000_AT_CellularStack::socket_accept");
00057     return NSAPI_ERROR_UNSUPPORTED ;
00058 }
00059 
00060 // Callback for Socket Receive URC.
00061 void RM1000_AT_CellularStack::RUSORCV_URC()
00062 {
00063     int a, b;
00064     CellularSocket *socket;
00065 
00066     a = _at.read_int();
00067     b = _at.read_int();
00068     socket = find_socket(a);
00069     if (socket != NULL) {
00070         socket->pending_bytes = b;
00071         // No debug prints here as they can affect timing
00072         // and cause data loss in UARTSerial
00073         if (socket->_cb != NULL) {
00074             socket->_cb(socket->_data);
00075         }
00076     }
00077 }
00078 
00079 // Callback for Socket Close URC.
00080 void RM1000_AT_CellularStack::RUSOCL_URC()
00081 {
00082     int a;
00083     CellularSocket *socket;
00084 
00085     a = _at.read_int();
00086     socket = find_socket(a);
00087     clear_socket(socket);
00088 }
00089 
00090 int RM1000_AT_CellularStack::get_max_socket_count()
00091 {
00092     tr_debug("RM1000_AT_CellularStack::get_max_socket_count");
00093     return RM1000_MAX_SOCKET;
00094 }
00095 
00096 bool RM1000_AT_CellularStack::is_protocol_supported(nsapi_protocol_t protocol)
00097 {
00098     return (protocol == NSAPI_UDP  || protocol == NSAPI_TCP );
00099 }
00100 
00101 nsapi_error_t RM1000_AT_CellularStack::create_socket_impl(CellularSocket *socket)
00102 {
00103     tr_debug("RM1000_AT_CellularStack::create_socket_impl");
00104 
00105     int sock_id = SOCKET_UNUSED;
00106 
00107     nsapi_error_t err = NSAPI_ERROR_OK ;
00108     if (socket->proto == NSAPI_UDP ) {
00109         err = _at.at_cmd_int("+RSOCR", "=0", sock_id);
00110     } else if (socket->proto == NSAPI_TCP ) {
00111         err = _at.at_cmd_int("+RSOCR", "=1", sock_id);
00112     } // Unsupported protocol is checked in "is_protocol_supported" function
00113 
00114     if ((err != NSAPI_ERROR_OK ) || (sock_id == -1)) {
00115         tr_error("RM1000_AT_CellularStack::create_socket_impl error sock_id=%d err=%d", sock_id, err);
00116         return NSAPI_ERROR_NO_SOCKET ;
00117     }
00118 
00119     // Check for duplicate socket id delivered by modem
00120     for (int i = 0; i < RM1000_MAX_SOCKET; i++) {
00121         CellularSocket *sock = _socket[i];
00122         if (sock && sock != socket && sock->id == sock_id) {
00123             return NSAPI_ERROR_NO_SOCKET ;
00124         }
00125     }
00126 
00127     socket->id = sock_id;
00128 
00129     return err;
00130 }
00131 
00132 nsapi_error_t RM1000_AT_CellularStack::socket_connect(nsapi_socket_t handle, const SocketAddress &addr)
00133 {
00134     tr_debug("RM1000_AT_CellularStack::socket_connect");
00135 
00136     CellularSocket *socket = (CellularSocket *)handle;
00137 
00138     if (socket) {
00139         if (socket->id == SOCKET_UNUSED) {
00140             nsapi_error_t err = create_socket_impl(socket);
00141             if (err != NSAPI_ERROR_OK ) {
00142                 return err;
00143             }
00144         }
00145     } else {
00146         return NSAPI_ERROR_DEVICE_ERROR ;
00147     }
00148 
00149     _at.lock();
00150     _at.cmd_start("AT+RSOCO=");
00151     _at.write_int(socket->id);
00152     _at.write_string(addr.get_ip_address(), false);
00153     _at.write_int(addr.get_port());
00154     _at.cmd_stop();
00155     _at.resp_start("+RSOCO:");
00156     int socket_id = _at.read_int();
00157     _at.resp_stop();
00158     nsapi_error_t error = _at.get_last_error();
00159     _at.unlock();
00160 
00161     if ((error == NSAPI_ERROR_OK ) && (socket_id == socket->id)) {
00162         socket->remoteAddress = addr;
00163         socket->connected = true;
00164         return NSAPI_ERROR_OK ;
00165     }
00166 
00167     return NSAPI_ERROR_NO_CONNECTION ;
00168 }
00169 
00170 nsapi_size_or_error_t RM1000_AT_CellularStack::socket_sendto_impl(CellularSocket *socket, const SocketAddress &address,
00171                                                                   const void *data, nsapi_size_t size)
00172 {
00173     tr_debug("RM1000_AT_CellularStack::socket_sendto_impl");
00174 
00175     int sent_len = 0;
00176     pollfh fhs;
00177     fhs.fh = _at.get_file_handle();
00178     fhs.events = POLLIN;
00179 
00180     bool success = true;
00181     const char *buf = (const char *) data;
00182     nsapi_size_t blk = RM1000_MAX_PACKET_SIZE;
00183     nsapi_size_t count = size;
00184 
00185     while ((count > 0) && success) {
00186         if (count < blk) {
00187             blk = count;
00188         }
00189         _at.cmd_start("AT+RSOSND=");
00190         _at.write_int(socket->id);
00191         _at.write_int(blk);
00192         if (socket->proto == NSAPI_UDP ) {
00193             _at.write_string(address.get_ip_address(), false);
00194             _at.write_int(address.get_port());
00195         }
00196         _at.cmd_stop();
00197         (void)poll(&fhs, 1, 50);
00198         _at.write_bytes((uint8_t *)buf, blk);
00199 
00200         _at.resp_start("+RSOSND:");
00201         _at.skip_param(); // skip socket id
00202         sent_len = _at.read_int();
00203         _at.resp_stop();
00204 
00205         if ((sent_len >= (int) blk) &&
00206                 (_at.get_last_error() == NSAPI_ERROR_OK )) {
00207         } else {
00208             success = false;
00209         }
00210 
00211         buf += blk;
00212         count -= blk;
00213     }
00214 
00215     if (success && _at.get_last_error() == NSAPI_ERROR_OK ) {
00216         return size - count;
00217     }
00218 
00219     return _at.get_last_error();
00220 }
00221 
00222 nsapi_size_or_error_t RM1000_AT_CellularStack::socket_recvfrom_impl(CellularSocket *socket, SocketAddress *address,
00223                                                                     void *buffer, nsapi_size_t size)
00224 {
00225     tr_debug("RM1000_AT_CellularStack::socket_recvfrom_impl");
00226 
00227     nsapi_size_or_error_t nsapi_error_size = NSAPI_ERROR_DEVICE_ERROR ;
00228     bool success = true;
00229     nsapi_size_t read_blk;
00230     nsapi_size_t count = 0;
00231     nsapi_size_t rsorcv_sz;
00232     char ipAddress[NSAPI_IP_SIZE];
00233     int port = 0;
00234     Timer timer;
00235 
00236     if (socket->pending_bytes == 0) {
00237         _at.process_oob();
00238         if (socket->pending_bytes == 0) {
00239             return NSAPI_ERROR_WOULD_BLOCK ;
00240         }
00241     }
00242 
00243     timer.start();
00244     while (success && (size > 0)) {
00245         read_blk = RM1000_MAX_PACKET_SIZE;
00246         if (read_blk > size) {
00247             read_blk = size;
00248         }
00249         if (socket->pending_bytes > 0) {
00250             _at.cmd_start_stop("+RSORCV", "=", "%d%d", socket->id, read_blk);
00251 
00252             _at.resp_start("+RSORCV:");
00253             _at.skip_param(); // receiving socket id
00254             rsorcv_sz = _at.read_int();
00255             if (socket->proto == NSAPI_UDP ) {
00256                 _at.read_string(ipAddress, sizeof(ipAddress));
00257                 port = _at.read_int();
00258             }
00259             if (rsorcv_sz > size) {
00260                 rsorcv_sz = size;
00261             }
00262             _at.read_bytes((uint8_t *)buffer + count, rsorcv_sz);
00263             _at.resp_stop();
00264 
00265             // Must use what +RSORCV returns here as it may be less or more than we asked for
00266             if (rsorcv_sz > socket->pending_bytes) {
00267                 socket->pending_bytes = 0;
00268             } else {
00269                 socket->pending_bytes -= rsorcv_sz;
00270             }
00271 
00272             if (rsorcv_sz > 0) {
00273                 count += rsorcv_sz;
00274                 size -= rsorcv_sz;
00275             } else {
00276                 // read() should not fail
00277                 success = false;
00278             }
00279         }  else if (timer.read_ms() < SOCKET_TIMEOUT) {
00280             // Wait for URCs
00281             _at.process_oob();
00282         } else {
00283             if (count == 0) {
00284                 // Timeout with nothing received
00285                 success = false;
00286             }
00287             break;
00288         }
00289     }
00290     timer.stop();
00291 
00292     if (!count || (_at.get_last_error() != NSAPI_ERROR_OK )) {
00293         return NSAPI_ERROR_WOULD_BLOCK ;
00294     } else {
00295         nsapi_error_size = count;
00296     }
00297 
00298     if (success && socket->proto == NSAPI_UDP  && address) {
00299         address->set_ip_address(ipAddress);
00300         address->get_ip_address();
00301         address->set_port(port);
00302     }
00303 
00304     return nsapi_error_size;
00305 }
00306 
00307 nsapi_error_t RM1000_AT_CellularStack::socket_close_impl(int sock_id)
00308 {
00309     tr_debug("RM1000_AT_CellularStack::socket_close_impl");
00310 
00311     return _at.at_cmd_discard("+RSOCL", "=", "%d", sock_id);
00312 }
00313 
00314 // Clear out the storage for a socket
00315 void RM1000_AT_CellularStack::clear_socket(CellularSocket *socket)
00316 {
00317     if (socket != NULL) {
00318         socket->id       = SOCKET_UNUSED;
00319         socket->pending_bytes = 0;
00320         socket->_cb      = NULL;
00321         socket->_data    = NULL;
00322     }
00323 }
00324 
00325 nsapi_error_t RM1000_AT_CellularStack::gethostbyname(const char *host, SocketAddress *address, nsapi_version_t version, const char *interface_name)
00326 {
00327     tr_debug("RM1000_AT_CellularStack::gethostbyname");
00328 
00329     char ipAddress[NSAPI_IP_SIZE];
00330     nsapi_error_t err = NSAPI_ERROR_NO_CONNECTION ;
00331 
00332     _at.lock();
00333     if (address->set_ip_address(host)) {
00334         err = NSAPI_ERROR_OK ;
00335     } else {
00336         // This interrogation can sometimes take longer than the usual 8 seconds
00337         _at.cmd_start("AT+RDNS=");
00338         _at.write_string(host, false);
00339         _at.cmd_stop();
00340 
00341         _at.set_at_timeout(70000);
00342         _at.resp_start("+RDNS:");
00343         if (_at.info_resp()) {
00344             _at.read_string(ipAddress, sizeof(ipAddress));
00345             if (address->set_ip_address(ipAddress)) {
00346                 err = NSAPI_ERROR_OK ;
00347             }
00348         }
00349         _at.resp_stop();
00350         _at.restore_at_timeout();
00351     }
00352     _at.unlock();
00353 
00354     return err;
00355 }