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
UBLOX_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 "UBLOX_AT_CellularStack.h" 00019 #include "mbed_poll.h" 00020 00021 using namespace mbed; 00022 using namespace mbed_cellular_util; 00023 00024 UBLOX_AT_CellularStack::UBLOX_AT_CellularStack(ATHandler &atHandler, int cid, nsapi_ip_stack_t stack_type, AT_CellularDevice &device) : 00025 AT_CellularStack(atHandler, cid, stack_type, device) 00026 { 00027 // URC handlers for sockets 00028 _at.set_urc_handler("+UUSORD:", callback(this, &UBLOX_AT_CellularStack::UUSORD_URC)); 00029 _at.set_urc_handler("+UUSORF:", callback(this, &UBLOX_AT_CellularStack::UUSORF_URC)); 00030 _at.set_urc_handler("+UUSOCL:", callback(this, &UBLOX_AT_CellularStack::UUSOCL_URC)); 00031 _at.set_urc_handler("+UUPSDD:", callback(this, &UBLOX_AT_CellularStack::UUPSDD_URC)); 00032 } 00033 00034 UBLOX_AT_CellularStack::~UBLOX_AT_CellularStack() 00035 { 00036 } 00037 00038 nsapi_error_t UBLOX_AT_CellularStack::socket_listen(nsapi_socket_t handle, int backlog) 00039 { 00040 return NSAPI_ERROR_UNSUPPORTED ; 00041 } 00042 00043 nsapi_error_t UBLOX_AT_CellularStack::socket_accept(void *server, void **socket, SocketAddress *addr) 00044 { 00045 return NSAPI_ERROR_UNSUPPORTED ; 00046 } 00047 00048 // Callback for Socket Read URC. 00049 void UBLOX_AT_CellularStack::UUSORD_URC() 00050 { 00051 int a, b; 00052 CellularSocket *socket; 00053 00054 a = _at.read_int(); 00055 b = _at.read_int(); 00056 00057 socket = find_socket(a); 00058 if (socket != NULL) { 00059 socket->pending_bytes = b; 00060 // No debug prints here as they can affect timing 00061 // and cause data loss in UARTSerial 00062 if (socket->_cb != NULL) { 00063 socket->_cb(socket->_data); 00064 } 00065 } 00066 } 00067 00068 // Callback for Socket Read From URC. 00069 void UBLOX_AT_CellularStack::UUSORF_URC() 00070 { 00071 int a, b; 00072 CellularSocket *socket; 00073 00074 a = _at.read_int(); 00075 b = _at.read_int(); 00076 00077 socket = find_socket(a); 00078 if (socket != NULL) { 00079 socket->pending_bytes = b; 00080 // No debug prints here as they can affect timing 00081 // and cause data loss in UARTSerial 00082 if (socket->_cb != NULL) { 00083 socket->_cb(socket->_data); 00084 } 00085 } 00086 } 00087 00088 // Callback for Socket Close URC. 00089 void UBLOX_AT_CellularStack::UUSOCL_URC() 00090 { 00091 int a; 00092 CellularSocket *socket; 00093 00094 a = _at.read_int(); 00095 socket = find_socket(a); 00096 clear_socket(socket); 00097 } 00098 00099 // Callback for UUPSDD. 00100 void UBLOX_AT_CellularStack::UUPSDD_URC() 00101 { 00102 int a; 00103 CellularSocket *socket; 00104 00105 a = _at.read_int(); 00106 socket = find_socket(a); 00107 clear_socket(socket); 00108 } 00109 00110 int UBLOX_AT_CellularStack::get_max_socket_count() 00111 { 00112 return UBLOX_MAX_SOCKET; 00113 } 00114 00115 bool UBLOX_AT_CellularStack::is_protocol_supported(nsapi_protocol_t protocol) 00116 { 00117 return (protocol == NSAPI_UDP || protocol == NSAPI_TCP ); 00118 } 00119 00120 nsapi_error_t UBLOX_AT_CellularStack::create_socket_impl(CellularSocket *socket) 00121 { 00122 int sock_id = SOCKET_UNUSED; 00123 00124 nsapi_error_t err = NSAPI_ERROR_OK ; 00125 if (socket->proto == NSAPI_UDP ) { 00126 err = _at.at_cmd_int("+USOCR", "=17", sock_id); 00127 } else if (socket->proto == NSAPI_TCP ) { 00128 err = _at.at_cmd_int("+USOCR", "=6", sock_id); 00129 } // Unsupported protocol is checked in "is_protocol_supported" function 00130 00131 if ((err != NSAPI_ERROR_OK ) || (sock_id == -1)) { 00132 return NSAPI_ERROR_NO_SOCKET ; 00133 } 00134 00135 // Check for duplicate socket id delivered by modem 00136 for (int i = 0; i < UBLOX_MAX_SOCKET; i++) { 00137 CellularSocket *sock = _socket[i]; 00138 if (sock && sock != socket && sock->id == sock_id) { 00139 return NSAPI_ERROR_NO_SOCKET ; 00140 } 00141 } 00142 00143 socket->started = true; 00144 socket->id = sock_id; 00145 00146 return err; 00147 } 00148 00149 nsapi_error_t UBLOX_AT_CellularStack::socket_connect(nsapi_socket_t handle, const SocketAddress &addr) 00150 { 00151 CellularSocket *socket = (CellularSocket *)handle; 00152 00153 if (socket) { 00154 if (socket->id == SOCKET_UNUSED) { 00155 nsapi_error_t err = create_socket_impl(socket); 00156 if (err != NSAPI_ERROR_OK ) { 00157 return err; 00158 } 00159 } 00160 } else { 00161 return NSAPI_ERROR_DEVICE_ERROR ; 00162 } 00163 00164 nsapi_error_t err = _at.at_cmd_discard("+USOCO", "=", "%d%s%d", socket->id, addr.get_ip_address(), addr.get_port()); 00165 00166 if (err == NSAPI_ERROR_OK ) { 00167 socket->remoteAddress = addr; 00168 socket->connected = true; 00169 return NSAPI_ERROR_OK ; 00170 } 00171 00172 return NSAPI_ERROR_NO_CONNECTION ; 00173 } 00174 00175 nsapi_size_or_error_t UBLOX_AT_CellularStack::socket_sendto_impl(CellularSocket *socket, const SocketAddress &address, 00176 const void *data, nsapi_size_t size) 00177 { 00178 MBED_ASSERT(socket->id != -1); 00179 00180 int sent_len = 0; 00181 pollfh fhs; 00182 fhs.fh = _at.get_file_handle(); 00183 fhs.events = POLLIN; 00184 00185 if (socket->proto == NSAPI_UDP ) { 00186 if (size > UBLOX_MAX_PACKET_SIZE) { 00187 return NSAPI_ERROR_PARAMETER ; 00188 } 00189 _at.cmd_start_stop("+USOST", "=", "%d%s%d%d", socket->id, address.get_ip_address(), address.get_port(), size); 00190 00191 (void)poll(&fhs, 1, 50); 00192 _at.write_bytes((uint8_t *)data, size); 00193 00194 _at.resp_start("+USOST:"); 00195 _at.skip_param(); // skip socket id 00196 sent_len = _at.read_int(); 00197 _at.resp_stop(); 00198 00199 if ((_at.get_last_error() == NSAPI_ERROR_OK )) { 00200 return sent_len; 00201 } 00202 } else if (socket->proto == NSAPI_TCP ) { 00203 bool success = true; 00204 const char *buf = (const char *) data; 00205 nsapi_size_t blk = UBLOX_MAX_PACKET_SIZE; 00206 nsapi_size_t count = size; 00207 00208 while ((count > 0) && success) { 00209 if (count < blk) { 00210 blk = count; 00211 } 00212 _at.cmd_start_stop("+USOWR", "=", "%d%d", socket->id, blk); 00213 00214 (void)poll(&fhs, 1, 50); 00215 _at.write_bytes((uint8_t *)buf, blk); 00216 00217 _at.resp_start("+USOWR:"); 00218 _at.skip_param(); // skip socket id 00219 sent_len = _at.read_int(); 00220 _at.resp_stop(); 00221 00222 if ((sent_len >= (int) blk) && 00223 (_at.get_last_error() == NSAPI_ERROR_OK )) { 00224 } else { 00225 success = false; 00226 } 00227 00228 buf += blk; 00229 count -= blk; 00230 } 00231 00232 if (success && _at.get_last_error() == NSAPI_ERROR_OK ) { 00233 return size - count; 00234 } 00235 } 00236 00237 return _at.get_last_error(); 00238 } 00239 00240 nsapi_size_or_error_t UBLOX_AT_CellularStack::socket_recvfrom_impl(CellularSocket *socket, SocketAddress *address, 00241 void *buffer, nsapi_size_t size) 00242 { 00243 MBED_ASSERT(socket->id != -1); 00244 00245 nsapi_size_or_error_t nsapi_error_size = NSAPI_ERROR_DEVICE_ERROR ; 00246 bool success = true; 00247 nsapi_size_t read_blk; 00248 nsapi_size_t count = 0; 00249 nsapi_size_t usorf_sz; 00250 char ipAddress[NSAPI_IP_SIZE]; 00251 uint8_t ch = 0; 00252 int port = 0; 00253 Timer timer; 00254 00255 if (socket->pending_bytes == 0) { 00256 _at.process_oob(); 00257 if (socket->pending_bytes == 0) { 00258 return NSAPI_ERROR_WOULD_BLOCK ; 00259 } 00260 } 00261 00262 timer.start(); 00263 if (socket->proto == NSAPI_UDP ) { 00264 while (success && (size > 0)) { 00265 read_blk = UBLOX_MAX_PACKET_SIZE; 00266 if (read_blk > size) { 00267 read_blk = size; 00268 } 00269 if (socket->pending_bytes > 0) { 00270 _at.cmd_start_stop("+USORF", "=", "%d%d", socket->id, read_blk); 00271 00272 _at.resp_start("+USORF:"); 00273 _at.skip_param(); // receiving socket id 00274 _at.read_string(ipAddress, sizeof(ipAddress)); 00275 port = _at.read_int(); 00276 usorf_sz = _at.read_int(); 00277 if (usorf_sz > size) { 00278 usorf_sz = size; 00279 } 00280 _at.read_bytes(&ch, 1); 00281 _at.read_bytes((uint8_t *)buffer + count, usorf_sz); 00282 _at.resp_stop(); 00283 00284 // Must use what +USORF returns here as it may be less or more than we asked for 00285 if (usorf_sz > socket->pending_bytes) { 00286 socket->pending_bytes = 0; 00287 } else { 00288 socket->pending_bytes -= usorf_sz; 00289 } 00290 00291 if (usorf_sz > 0) { 00292 count += usorf_sz; 00293 size -= usorf_sz; 00294 } else { 00295 // read() should not fail 00296 success = false; 00297 } 00298 } else if (timer.read_ms() < SOCKET_TIMEOUT) { 00299 // Wait for URCs 00300 _at.process_oob(); 00301 } else { 00302 if (count == 0) { 00303 // Timeout with nothing received 00304 success = false; 00305 } 00306 break; 00307 } 00308 } 00309 } else if (socket->proto == NSAPI_TCP ) { 00310 while (success && (size > 0)) { 00311 read_blk = UBLOX_MAX_PACKET_SIZE; 00312 if (read_blk > size) { 00313 read_blk = size; 00314 } 00315 if (socket->pending_bytes > 0) { 00316 _at.cmd_start_stop("+USORD", "=", "%d%d", socket->id, read_blk); 00317 00318 _at.resp_start("+USORD:"); 00319 _at.skip_param(); // receiving socket id 00320 usorf_sz = _at.read_int(); 00321 if (usorf_sz > size) { 00322 usorf_sz = size; 00323 } 00324 _at.read_bytes(&ch, 1); 00325 _at.read_bytes((uint8_t *)buffer + count, usorf_sz); 00326 _at.resp_stop(); 00327 00328 // Must use what +USORD returns here as it may be less or more than we asked for 00329 if (usorf_sz > socket->pending_bytes) { 00330 socket->pending_bytes = 0; 00331 } else { 00332 socket->pending_bytes -= usorf_sz; 00333 } 00334 00335 if (usorf_sz > 0) { 00336 count += usorf_sz; 00337 size -= usorf_sz; 00338 } else { 00339 success = false; 00340 } 00341 } else if (timer.read_ms() < SOCKET_TIMEOUT) { 00342 // Wait for URCs 00343 _at.process_oob(); 00344 } else { 00345 if (count == 0) { 00346 // Timeout with nothing received 00347 success = false; 00348 } 00349 break; 00350 } 00351 } 00352 } 00353 timer.stop(); 00354 00355 socket->pending_bytes = 0; 00356 if (!count || (_at.get_last_error() != NSAPI_ERROR_OK )) { 00357 return NSAPI_ERROR_WOULD_BLOCK ; 00358 } else { 00359 nsapi_error_size = count; 00360 } 00361 00362 if (success && socket->proto == NSAPI_UDP && address) { 00363 address->set_ip_address(ipAddress); 00364 address->get_ip_address(); 00365 address->set_port(port); 00366 } 00367 00368 return nsapi_error_size; 00369 } 00370 00371 nsapi_error_t UBLOX_AT_CellularStack::socket_close_impl(int sock_id) 00372 { 00373 return _at.at_cmd_discard("+USOCL", "=", "%d", sock_id); 00374 } 00375 00376 // Find or create a socket from the list. 00377 UBLOX_AT_CellularStack::CellularSocket *UBLOX_AT_CellularStack::find_socket(int id) 00378 { 00379 CellularSocket *socket = NULL; 00380 00381 for (unsigned int x = 0; (socket == NULL) && (x < UBLOX_MAX_SOCKET); x++) { 00382 if (_socket) { 00383 if (_socket[x]->id == id) { 00384 socket = (_socket[x]); 00385 } 00386 } 00387 } 00388 00389 return socket; 00390 } 00391 00392 00393 // Clear out the storage for a socket 00394 void UBLOX_AT_CellularStack::clear_socket(CellularSocket *socket) 00395 { 00396 if (socket != NULL) { 00397 socket->id = SOCKET_UNUSED; 00398 socket->started = false; 00399 socket->pending_bytes = 0; 00400 socket->closed = true; 00401 if (socket->_cb) { 00402 socket->_cb(socket->_data); 00403 } 00404 } 00405 } 00406 00407 const char *UBLOX_AT_CellularStack::get_ip_address() 00408 { 00409 _at.lock(); 00410 _at.cmd_start_stop("+UPSND", "=", "%d%d", PROFILE, 0); 00411 00412 _at.resp_start("+UPSND:"); 00413 if (_at.info_resp()) { 00414 _at.skip_param(); 00415 _at.skip_param(); 00416 int len = _at.read_string(_ip, NSAPI_IPv4_SIZE); 00417 if (len == -1) { 00418 _ip[0] = '\0'; 00419 _at.unlock(); 00420 // no IPV4 address, return 00421 return NULL; 00422 } 00423 00424 // in case stack type is not IPV4 only, try to look also for IPV6 address 00425 if (_stack_type != IPV4_STACK) { 00426 len = _at.read_string(_ip, PDP_IPV6_SIZE); 00427 } 00428 } 00429 _at.resp_stop(); 00430 _at.unlock(); 00431 00432 // we have at least IPV4 address 00433 convert_ipv6(_ip); 00434 00435 return _ip; 00436 } 00437 00438 nsapi_error_t UBLOX_AT_CellularStack::gethostbyname(const char *host, SocketAddress *address, nsapi_version_t version, const char *interface_name) 00439 { 00440 char ipAddress[NSAPI_IP_SIZE]; 00441 nsapi_error_t err = NSAPI_ERROR_NO_CONNECTION ; 00442 00443 _at.lock(); 00444 if (address->set_ip_address(host)) { 00445 err = NSAPI_ERROR_OK ; 00446 } else { 00447 #ifdef UBX_MDM_SARA_R41XM 00448 _at.set_at_timeout(70000); 00449 #else 00450 _at.set_at_timeout(120000); 00451 #endif 00452 // This interrogation can sometimes take longer than the usual 8 seconds 00453 _at.cmd_start_stop("+UDNSRN", "=0,", "%s", host); 00454 00455 _at.resp_start("+UDNSRN:"); 00456 if (_at.info_resp()) { 00457 _at.read_string(ipAddress, sizeof(ipAddress)); 00458 00459 if (address->set_ip_address(ipAddress)) { 00460 err = NSAPI_ERROR_OK ; 00461 } 00462 } 00463 _at.resp_stop(); 00464 _at.restore_at_timeout(); 00465 } 00466 _at.unlock(); 00467 00468 return err; 00469 }
Generated on Tue Jul 12 2022 13:55:01 by
