Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
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 }
Generated on Tue Jul 12 2022 13:54:47 by
