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