Implementation of the CellularInterface for u-blox C030 boards with N2xx modems. Note: requires the N211 module firmware to be at least 06.57 A01.02.
Dependents: example-ublox-cellular-interface HelloMQTT example-ublox-cellular-interface_r410M example-ublox-mbed-client ... more
UbloxATCellularInterfaceN2xx.cpp
00001 /* Copyright (c) 2017 ublox Limited 00002 * 00003 * Licensed under the Apache License, Version 2.0 (the "License"); 00004 * you may not use this file except in compliance with the License. 00005 * You may obtain a copy of the License at 00006 * 00007 * http://www.apache.org/licenses/LICENSE-2.0 00008 * 00009 * Unless required by applicable law or agreed to in writing, software 00010 * distributed under the License is distributed on an "AS IS" BASIS, 00011 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00012 * See the License for the specific language governing permissions and 00013 * limitations under the License. 00014 */ 00015 00016 #include "UbloxATCellularInterfaceN2xx.h" 00017 #include "mbed_poll.h" 00018 #include "nsapi.h" 00019 #include "APN_db.h" 00020 #ifdef FEATURE_COMMON_PAL 00021 #include "mbed_trace.h" 00022 #define TRACE_GROUP "UACI" 00023 #else 00024 #define tr_debug(format, ...) debug_if(_debug_trace_on, format "\n", ## __VA_ARGS__) 00025 #define tr_info(format, ...) debug_if(_debug_trace_on, format "\n", ## __VA_ARGS__) 00026 #define tr_warn(format, ...) debug_if(_debug_trace_on, format "\n", ## __VA_ARGS__) 00027 #define tr_error(format, ...) debug_if(_debug_trace_on, format "\n", ## __VA_ARGS__) 00028 #endif 00029 00030 // When calling the SendTo function, the large hex string for the bytes to send is chopped into chunks 00031 #define SENDTO_CHUNK_SIZE 50 00032 00033 /********************************************************************** 00034 * PRIVATE METHODS 00035 **********************************************************************/ 00036 00037 // Event thread for asynchronous received data handling. 00038 void UbloxATCellularInterfaceN2xx::handle_event(){ 00039 pollfh fhs; 00040 int count; 00041 int at_timeout; 00042 00043 fhs.fh = _fh; 00044 fhs.events = POLLIN; 00045 00046 while (true) { 00047 count = poll(&fhs, 1, 1000); 00048 if (count > 0 && (fhs.revents & POLLIN)) { 00049 LOCK(); 00050 at_timeout = _at_timeout; 00051 at_set_timeout(10); // Avoid blocking but also make sure we don't 00052 // time out if we get ahead of the serial port 00053 _at->debug_on(false); // Debug here screws with the test output 00054 // Let the URCs run 00055 _at->recv(UNNATURAL_STRING); 00056 _at->debug_on(_debug_trace_on); 00057 at_set_timeout(at_timeout); 00058 UNLOCK(); 00059 } 00060 } 00061 } 00062 00063 // Find or create a socket from the list. 00064 UbloxATCellularInterfaceN2xx::SockCtrl * UbloxATCellularInterfaceN2xx::find_socket(int modem_handle) 00065 { 00066 UbloxATCellularInterfaceN2xx::SockCtrl *socket = NULL; 00067 00068 for (unsigned int x = 0; (socket == NULL) && (x < sizeof(_sockets) / sizeof(_sockets[0])); x++) { 00069 if (_sockets[x].modem_handle == modem_handle) { 00070 socket = &(_sockets[x]); 00071 } 00072 } 00073 00074 return socket; 00075 } 00076 00077 // Clear out the storage for a socket 00078 void UbloxATCellularInterfaceN2xx::clear_socket(UbloxATCellularInterfaceN2xx::SockCtrl * socket) 00079 { 00080 if (socket != NULL) { 00081 socket->modem_handle = SOCKET_UNUSED; 00082 socket->pending = 0; 00083 socket->callback = NULL; 00084 socket->data = NULL; 00085 } 00086 } 00087 00088 // Check that a socket pointer is valid 00089 bool UbloxATCellularInterfaceN2xx::check_socket(SockCtrl * socket) 00090 { 00091 bool success = false; 00092 00093 if (socket != NULL) { 00094 for (unsigned int x = 0; !success && (x < sizeof(_sockets) / sizeof(_sockets[0])); x++) { 00095 if (socket == &(_sockets[x])) { 00096 success = true; 00097 } 00098 } 00099 } 00100 00101 return success; 00102 } 00103 00104 // Callback for Socket Read From URC. 00105 void UbloxATCellularInterfaceN2xx::NSONMI_URC() 00106 { 00107 int a; 00108 int b; 00109 char buf[32]; 00110 SockCtrl *socket; 00111 00112 // Note: not calling _at->recv() from here as we're 00113 // already in an _at->recv() 00114 // +UUSORF: <socket>,<length> 00115 if (read_at_to_newline(buf, sizeof (buf)) > 0) { 00116 tr_debug("NSONMI URC"); 00117 if (sscanf(buf, ":%d,%d", &a, &b) == 2) { 00118 socket = find_socket(a); 00119 if (socket != NULL) { 00120 socket->pending += b; 00121 tr_debug("Socket 0x%08x: modem handle %d has %d byte(s) pending", 00122 (unsigned int) socket, a, socket->pending); 00123 if (socket->callback != NULL) { 00124 tr_debug("***** Calling callback..."); 00125 socket->callback(socket->data); 00126 tr_debug("***** Callback finished"); 00127 } else { 00128 tr_debug("No callback found for socket."); 00129 } 00130 } else { 00131 tr_debug("Can't find socket with modem handle %d", a); 00132 } 00133 } 00134 } 00135 } 00136 00137 /********************************************************************** 00138 * PROTECTED METHODS: GENERAL 00139 **********************************************************************/ 00140 00141 // Get the next set of credentials, based on IMSI. 00142 void UbloxATCellularInterfaceN2xx::get_next_credentials(const char * config) 00143 { 00144 if (config) { 00145 _apn = _APN_GET(config); 00146 _uname = _APN_GET(config); 00147 _pwd = _APN_GET(config); 00148 } 00149 00150 _apn = _apn ? _apn : ""; 00151 _uname = _uname ? _uname : ""; 00152 _pwd = _pwd ? _pwd : ""; 00153 } 00154 00155 /********************************************************************** 00156 * PROTECTED METHODS: NETWORK INTERFACE and SOCKETS 00157 **********************************************************************/ 00158 00159 // Gain access to us. 00160 NetworkStack *UbloxATCellularInterfaceN2xx::get_stack() 00161 { 00162 return this; 00163 } 00164 00165 // Create a socket. 00166 nsapi_error_t UbloxATCellularInterfaceN2xx::socket_open(nsapi_socket_t *handle, 00167 nsapi_protocol_t proto) 00168 { 00169 nsapi_error_t nsapi_error = NSAPI_ERROR_DEVICE_ERROR; 00170 int modem_handle =0; 00171 SockCtrl *socket; 00172 00173 if (proto != NSAPI_UDP) { 00174 return NSAPI_ERROR_UNSUPPORTED; 00175 } 00176 00177 LOCK(); 00178 00179 // Find a free socket 00180 socket = find_socket(); 00181 if (socket != NULL) { 00182 tr_debug("socket_open(%d)", proto); 00183 if (_at->send("AT+NSOCR=\"DGRAM\",17,%d", _localListenPort) && 00184 _at->recv("%d\n", &modem_handle) && 00185 _at->recv("OK")) { 00186 tr_debug("Socket 0x%8x: handle %d was created", (unsigned int) socket, modem_handle); 00187 clear_socket(socket); 00188 socket->modem_handle = modem_handle; 00189 *handle = (nsapi_socket_t) socket; 00190 nsapi_error = NSAPI_ERROR_OK; 00191 } else { 00192 tr_error("Couldn't open socket using AT command"); 00193 } 00194 } else { 00195 tr_error("Can't find a socket to use"); 00196 nsapi_error = NSAPI_ERROR_NO_MEMORY; 00197 } 00198 00199 UNLOCK(); 00200 return nsapi_error; 00201 } 00202 00203 00204 // Close a socket. 00205 nsapi_error_t UbloxATCellularInterfaceN2xx::socket_close(nsapi_socket_t handle) 00206 { 00207 nsapi_error_t nsapi_error = NSAPI_ERROR_DEVICE_ERROR; 00208 SockCtrl *socket = (SockCtrl *) handle; 00209 LOCK(); 00210 00211 tr_debug("socket_close(0x%08x)", (unsigned int) handle); 00212 00213 MBED_ASSERT (check_socket(socket)); 00214 00215 if (_at->send("AT+NSOCL=%d", socket->modem_handle) && 00216 _at->recv("OK")) { 00217 clear_socket(socket); 00218 nsapi_error = NSAPI_ERROR_OK; 00219 } else { 00220 tr_error("Failed to close socket %d", socket->modem_handle); 00221 } 00222 00223 UNLOCK(); 00224 return nsapi_error; 00225 } 00226 00227 // Bind a local port to a socket. 00228 nsapi_error_t UbloxATCellularInterfaceN2xx::socket_bind(nsapi_socket_t handle, 00229 const SocketAddress &address) 00230 { 00231 return NSAPI_ERROR_UNSUPPORTED; 00232 } 00233 00234 // Connect to a socket 00235 nsapi_error_t UbloxATCellularInterfaceN2xx::socket_connect(nsapi_socket_t handle, 00236 const SocketAddress &address) 00237 { 00238 return NSAPI_ERROR_UNSUPPORTED; 00239 } 00240 00241 // Send to a socket. 00242 nsapi_size_or_error_t UbloxATCellularInterfaceN2xx::socket_send(nsapi_socket_t handle, 00243 const void *data, 00244 nsapi_size_t size) 00245 { 00246 return NSAPI_ERROR_UNSUPPORTED; 00247 } 00248 00249 // Send to an IP address. 00250 nsapi_size_or_error_t UbloxATCellularInterfaceN2xx::socket_sendto(nsapi_socket_t handle, 00251 const SocketAddress &address, 00252 const void *data, 00253 nsapi_size_t size) 00254 { 00255 nsapi_size_or_error_t nsapi_error_size = NSAPI_ERROR_DEVICE_ERROR; 00256 bool success = true; 00257 const char *buf = (const char *) data; 00258 nsapi_size_t blk = MAX_WRITE_SIZE_N2XX; 00259 nsapi_size_t count = size; 00260 SockCtrl *socket = (SockCtrl *) handle; 00261 00262 tr_debug("socket_sendto(0x%8x, %s(:%d), 0x%08x, %d)", (unsigned int) handle, 00263 address.get_ip_address(), address.get_port(), (unsigned int) data, size); 00264 00265 MBED_ASSERT (check_socket(socket)); 00266 00267 tr_debug("Max Write Size for SendTo: %d", MAX_WRITE_SIZE_N2XX); 00268 if (size > MAX_WRITE_SIZE_N2XX) { 00269 tr_warn("WARNING: packet length %d is too big for one UDP packet (max %d), will be fragmented.", size, MAX_WRITE_SIZE_N2XX); 00270 } 00271 00272 while ((count > 0) && success) { 00273 if (count < blk) { 00274 blk = count; 00275 } 00276 00277 // call the AT Helper function to send the bytes 00278 tr_debug("Sending %d bytes....", blk); 00279 int sent = sendto(socket, address, buf, blk); 00280 if (sent < 0) { 00281 tr_error("Something went wrong! %d", sent); 00282 return NSAPI_ERROR_DEVICE_ERROR; 00283 } 00284 00285 buf += sent; 00286 count -= sent; 00287 } 00288 00289 if (success) { 00290 nsapi_error_size = size - count; 00291 if (_debug_trace_on) { 00292 tr_debug("socket_sendto: %d \"%*.*s\"", size, size, size, (char *) data); 00293 } 00294 } 00295 00296 return nsapi_error_size; 00297 } 00298 00299 nsapi_size_or_error_t UbloxATCellularInterfaceN2xx::sendto(SockCtrl *socket, const SocketAddress &address, const char *buf, int size) { 00300 nsapi_size_or_error_t sent = NSAPI_ERROR_DEVICE_ERROR; 00301 int id; 00302 00303 char *dataStr = (char *) malloc((size * 2) + 1); 00304 if (dataStr == NULL) { 00305 tr_error("Couldn't allocate memory for hex string conversion."); 00306 return NSAPI_ERROR_NO_MEMORY; 00307 } 00308 00309 tr_debug("Converting byte array to hex string"); 00310 bin_to_hex(buf, size, dataStr); 00311 tr_debug("Got hex string"); 00312 00313 // AT+NSOSTF= socket, remote_addr, remote_port, length, data 00314 tr_debug("Writing AT+NSOSTF=<sktid>,<ipaddr>,<port>,<flags>,<size>,<hex string> command..."); 00315 char *cmdStr = (char *) malloc(50); 00316 if (cmdStr == NULL) { 00317 tr_error("Couldn't allocate memory for AT cmd string."); 00318 return NSAPI_ERROR_NO_MEMORY; 00319 } 00320 00321 int cmdsize = sprintf(cmdStr, "AT+NSOSTF=%d,\"%s\",%d,0x0,%d,\"", socket->modem_handle, address.get_ip_address(), address.get_port(), size); 00322 tr_debug("%s", cmdStr); 00323 00324 LOCK(); 00325 if (_at->write(cmdStr, cmdsize) && sendATChopped(dataStr)) 00326 { 00327 tr_debug("Finished sending AT+NSOST comamnd, reading back the 'sent' size..."); 00328 if (_at->recv("%d,%d\n", &id, &sent) && _at->recv("OK")) { 00329 tr_debug("Sent %d bytes on socket %d", sent, id); 00330 } else { 00331 tr_error("Didn't get the Sent size or OK"); 00332 } 00333 } else { 00334 tr_error("Didn't send the AT command!"); 00335 } 00336 UNLOCK(); 00337 00338 free(cmdStr); 00339 free(dataStr); 00340 00341 return sent; 00342 } 00343 00344 bool UbloxATCellularInterfaceN2xx::sendATChopped(const char *cmd) 00345 { 00346 char buff[SENDTO_CHUNK_SIZE]; 00347 tr_debug("Chopping up large AT text of %d characters.", strlen(cmd)); 00348 00349 while (*cmd != '\0') 00350 { 00351 int i=0; 00352 00353 for (i=0; i<SENDTO_CHUNK_SIZE; i++) { 00354 buff[i] = *cmd; 00355 00356 // if we have copied the NULL terminator, we can exit 00357 if (*cmd == '\0') 00358 break; 00359 00360 // still more characters to copy, so move along 00361 cmd++; 00362 } 00363 00364 // if we are at the end of the line, use the send command to 00365 // provide the \r\n terminator for the AT command 00366 if (*cmd == '\0') { 00367 tr_debug("send(%d): %s", i, buff); 00368 // write the last buffer... 00369 if (!_at->write(buff,i)) 00370 return false; 00371 00372 // ...send the enclosing quote to complete the AT command 00373 if (!_at->send("\"")) 00374 return false; 00375 } else { 00376 tr_debug("write(50): %s", buff); 00377 if (!_at->write(buff, 50)) 00378 return false; 00379 } 00380 } 00381 00382 return true; 00383 } 00384 00385 void UbloxATCellularInterfaceN2xx::bin_to_hex(const char *buff, unsigned int length, char *output) 00386 { 00387 char binHex[] = "0123456789ABCDEF"; 00388 00389 *output = '\0'; 00390 00391 for (; length > 0; --length) 00392 { 00393 unsigned char byte = *buff++; 00394 00395 *output++ = binHex[(byte >> 4) & 0x0F]; 00396 *output++ = binHex[byte & 0x0F]; 00397 } 00398 00399 *output++ = '\0'; 00400 } 00401 00402 // Receive from a socket, TCP style. 00403 nsapi_size_or_error_t UbloxATCellularInterfaceN2xx::socket_recv(nsapi_socket_t handle, 00404 void *data, 00405 nsapi_size_t size) 00406 { 00407 return NSAPI_ERROR_UNSUPPORTED; 00408 } 00409 00410 // Receive a packet over a UDP socket. 00411 nsapi_size_or_error_t UbloxATCellularInterfaceN2xx::socket_recvfrom(nsapi_socket_t handle, 00412 SocketAddress *address, 00413 void *data, 00414 nsapi_size_t size) 00415 { 00416 nsapi_size_or_error_t nsapi_error_size = NSAPI_ERROR_DEVICE_ERROR; 00417 bool success = true; 00418 char *buf = (char *) data; 00419 nsapi_size_t read_blk; 00420 nsapi_size_t count = 0; 00421 int at_timeout = _at_timeout; 00422 00423 char * tmpBuf = NULL; 00424 00425 Timer timer; 00426 SockCtrl *socket = (SockCtrl *) handle; 00427 00428 tr_debug("socket_recvfrom(0x%08x, 0x%08x, SIZE=%d)", (unsigned int) handle, (unsigned int) data, size); 00429 00430 MBED_ASSERT (check_socket(socket)); 00431 timer.start(); 00432 00433 while (success && (size > 0)) { 00434 LOCK(); 00435 at_timeout = _at_timeout; 00436 at_set_timeout(1000); 00437 00438 read_blk = MAX_READ_SIZE_N2XX; 00439 if (read_blk > size) { 00440 read_blk = size; 00441 } 00442 00443 if (socket->pending > 0) { 00444 tr_debug("Socket 0x%08x: modem handle %d has %d byte(s) pending", 00445 (unsigned int) socket, socket->modem_handle, socket->pending); 00446 00447 tmpBuf = (char *) malloc(read_blk); 00448 if (tmpBuf == NULL) { 00449 return NSAPI_ERROR_NO_MEMORY; 00450 } 00451 00452 // call the AT helper function to get the bytes 00453 nsapi_error_size = receivefrom(socket->modem_handle, address, read_blk, tmpBuf); 00454 00455 if (nsapi_error_size >= 0) { 00456 memcpy(buf, tmpBuf, nsapi_error_size); 00457 00458 if (read_blk != (uint32_t) nsapi_error_size) 00459 tr_debug("Requested size is not the same as the returned size."); 00460 00461 socket->pending -= nsapi_error_size; 00462 count += nsapi_error_size; 00463 buf += nsapi_error_size; 00464 size -= nsapi_error_size; 00465 00466 if (((uint32_t) nsapi_error_size < read_blk) || (nsapi_error_size == MAX_READ_SIZE_N2XX)) 00467 size = 0; // If we've received less than we asked for, or 00468 // the max size, then a whole UDP packet has arrived and 00469 // this means DONE. 00470 } else { 00471 // Should never fail to read when there is pending data 00472 success = false; 00473 } 00474 free(tmpBuf); 00475 } else if (timer.read_ms() < SOCKET_TIMEOUT) { 00476 // Wait for URCs 00477 tr_debug("Waiting for URC..."); 00478 _at->recv(UNNATURAL_STRING); 00479 } else { 00480 tr_debug("Nothing pending..."); 00481 if (count == 0) { 00482 tr_debug("Nothing received, so timeout with block"); 00483 // Timeout with nothing received 00484 nsapi_error_size = NSAPI_ERROR_WOULD_BLOCK; 00485 success = false; 00486 } 00487 size = 0; // This simply to cause an exit 00488 } 00489 00490 at_set_timeout(at_timeout); 00491 UNLOCK(); 00492 } 00493 timer.stop(); 00494 00495 if (success) { 00496 tr_debug("socket_recvfrom: %d SUCCESS!", count); 00497 nsapi_error_size = count; 00498 } else { 00499 tr_debug("socket_recvfrom: FAILED"); 00500 } 00501 00502 return nsapi_error_size; 00503 } 00504 00505 nsapi_size_or_error_t UbloxATCellularInterfaceN2xx::receivefrom(int modem_handle, SocketAddress *address, int length, char *buf) { 00506 char ipAddress[NSAPI_IP_SIZE]; 00507 nsapi_size_or_error_t size; 00508 00509 memset (ipAddress, 0, sizeof (ipAddress)); // Ensure terminator 00510 00511 if (length > MAX_READ_SIZE_N2XX) { 00512 return NSAPI_ERROR_UNSUPPORTED; 00513 } 00514 00515 char * tmpBuf = (char *) malloc(length*2); 00516 if (tmpBuf == NULL) 00517 return NSAPI_ERROR_NO_MEMORY; 00518 00519 int remaining; 00520 00521 _at->debug_on(false); // ABSOLUTELY no time for debug here if you want to 00522 // be able to read packets of any size without 00523 // losing characters in UARTSerial 00524 00525 // Ask for x bytes from Socket 00526 tr_debug("Requesting to read back %d bytes from socket %d", length, modem_handle); 00527 if (_at->send("AT+NSORF=%d,%d", modem_handle, length)) { 00528 unsigned int id, port; 00529 00530 // ReadFrom header, to get length - if no data then this will time out 00531 if (_at->recv("%d,\"%15[^\"]\",%d,%d,", &id, ipAddress, &port, &size)) { 00532 tr_debug("Socket RecvFrom: #%d: %d", id, size); 00533 00534 address->set_ip_address(ipAddress); 00535 address->set_port(port); 00536 00537 // read the beginning quote for this data 00538 _at->read(tmpBuf, 1); 00539 00540 // now read hex data 00541 if (_at->read(tmpBuf, size*2) == size*2) { 00542 00543 // convert to bytes 00544 hex_to_bin(tmpBuf, buf, size); 00545 00546 // read the "remaining" value - remembing there is an enclosing quote at the beginning of this read 00547 if (!_at->recv("\",%d\n", &remaining)) { 00548 tr_error("Failed reading the 'remaining' value after the received data."); 00549 size = NSAPI_ERROR_DEVICE_ERROR; 00550 } 00551 } 00552 } 00553 00554 // we should get the OK (even if there is no data to read) 00555 if (_at->recv("OK")) { 00556 tr_debug("Socket RecvFrom: Read %d bytes, %d bytes remaining.", size, remaining); 00557 } else { 00558 tr_error("Socket RecvFrom: Didn't receive OK from AT+NSORF command."); 00559 size = NSAPI_ERROR_DEVICE_ERROR; 00560 } 00561 } 00562 00563 _at->debug_on(_debug_trace_on); 00564 free(tmpBuf); 00565 00566 return size; 00567 } 00568 00569 char UbloxATCellularInterfaceN2xx::hex_char(char c) 00570 { 00571 if ('0' <= c && c <= '9') return (unsigned char)(c - '0'); 00572 if ('A' <= c && c <= 'F') return (unsigned char)(c - 'A' + 10); 00573 if ('a' <= c && c <= 'f') return (unsigned char)(c - 'a' + 10); 00574 return 0xFF; 00575 } 00576 00577 int UbloxATCellularInterfaceN2xx::hex_to_bin(const char* s, char * buff, int length) 00578 { 00579 int result; 00580 if (!s || !buff || length <= 0) return -1; 00581 00582 for (result = 0; *s; ++result) 00583 { 00584 unsigned char msn = hex_char(*s++); 00585 if (msn == 0xFF) return -1; 00586 unsigned char lsn = hex_char(*s++); 00587 if (lsn == 0xFF) return -1; 00588 unsigned char bin = (msn << 4) + lsn; 00589 00590 if (length-- <= 0) return -1; 00591 *buff++ = bin; 00592 } 00593 return result; 00594 } 00595 00596 // Attach an event callback to a socket, required for asynchronous 00597 // data reception 00598 void UbloxATCellularInterfaceN2xx::socket_attach(nsapi_socket_t handle, 00599 void (*callback)(void *), 00600 void *data) 00601 { 00602 SockCtrl *socket = (SockCtrl *) handle; 00603 00604 MBED_ASSERT (check_socket(socket)); 00605 00606 socket->callback = callback; 00607 socket->data = data; 00608 } 00609 00610 // Unsupported TCP server functions. 00611 nsapi_error_t UbloxATCellularInterfaceN2xx::socket_listen(nsapi_socket_t handle, 00612 int backlog) 00613 { 00614 return NSAPI_ERROR_UNSUPPORTED; 00615 } 00616 nsapi_error_t UbloxATCellularInterfaceN2xx::socket_accept(nsapi_socket_t server, 00617 nsapi_socket_t *handle, 00618 SocketAddress *address) 00619 { 00620 return NSAPI_ERROR_UNSUPPORTED; 00621 } 00622 00623 // Unsupported option functions. 00624 nsapi_error_t UbloxATCellularInterfaceN2xx::setsockopt(nsapi_socket_t handle, 00625 int level, int optname, 00626 const void *optval, 00627 unsigned optlen) 00628 { 00629 return NSAPI_ERROR_UNSUPPORTED; 00630 } 00631 nsapi_error_t UbloxATCellularInterfaceN2xx::getsockopt(nsapi_socket_t handle, 00632 int level, int optname, 00633 void *optval, 00634 unsigned *optlen) 00635 { 00636 return NSAPI_ERROR_UNSUPPORTED; 00637 } 00638 00639 /********************************************************************** 00640 * PUBLIC METHODS 00641 **********************************************************************/ 00642 00643 // Constructor. 00644 UbloxATCellularInterfaceN2xx::UbloxATCellularInterfaceN2xx(PinName tx, 00645 PinName rx, 00646 int baud, 00647 bool debug_on) 00648 { 00649 _sim_pin_check_change_pending = false; 00650 _sim_pin_check_change_pending_enabled_value = false; 00651 _sim_pin_change_pending = false; 00652 _sim_pin_change_pending_new_pin_value = NULL; 00653 _apn = NULL; 00654 _uname = NULL; 00655 _pwd = NULL; 00656 _connection_status_cb = NULL; 00657 00658 _localListenPort = 10000; 00659 00660 tr_debug("UbloxATCellularInterfaceN2xx Constructor"); 00661 00662 // Initialise sockets storage 00663 memset(_sockets, 0, sizeof(_sockets)); 00664 for (unsigned int socket = 0; socket < sizeof(_sockets) / sizeof(_sockets[0]); socket++) { 00665 _sockets[socket].modem_handle = SOCKET_UNUSED; 00666 _sockets[socket].callback = NULL; 00667 _sockets[socket].data = NULL; 00668 } 00669 00670 // The authentication to use 00671 _auth = NSAPI_SECURITY_UNKNOWN; 00672 00673 // Nullify the temporary IP address storage 00674 _ip = NULL; 00675 00676 // Initialise the base class, which starts the AT parser 00677 baseClassInit(tx, rx, baud, debug_on); 00678 00679 // Start the event handler thread for Rx data 00680 event_thread.start(callback(this, &UbloxATCellularInterfaceN2xx::handle_event)); 00681 00682 // URC handlers for sockets 00683 _at->oob("+NSONMI", callback(this, &UbloxATCellularInterfaceN2xx::NSONMI_URC)); 00684 } 00685 00686 // Destructor. 00687 UbloxATCellularInterfaceN2xx::~UbloxATCellularInterfaceN2xx() 00688 { 00689 // Free _ip if it was ever allocated 00690 free(_ip); 00691 } 00692 00693 // Set the authentication scheme. 00694 void UbloxATCellularInterfaceN2xx::set_authentication(nsapi_security_t auth) 00695 { 00696 _auth = auth; 00697 } 00698 00699 // Set APN, user name and password. 00700 void UbloxATCellularInterfaceN2xx::set_credentials(const char *apn, 00701 const char *uname, 00702 const char *pwd) 00703 { 00704 _apn = apn; 00705 _uname = uname; 00706 _pwd = pwd; 00707 } 00708 00709 // Set PIN. 00710 void UbloxATCellularInterfaceN2xx::set_sim_pin(const char *pin) { 00711 set_pin(pin); 00712 } 00713 00714 // Get the IP address of a host. 00715 nsapi_error_t UbloxATCellularInterfaceN2xx::gethostbyname(const char *host, 00716 SocketAddress *address, 00717 nsapi_version_t version) 00718 { 00719 nsapi_error_t nsapiError = NSAPI_ERROR_DEVICE_ERROR; 00720 tr_debug("GetHostByName: host= %s", host); 00721 if (address->set_ip_address(host)) { 00722 tr_debug("OK"); 00723 nsapiError = NSAPI_ERROR_OK; 00724 } else { 00725 tr_debug("Failed"); 00726 nsapiError = NSAPI_ERROR_UNSUPPORTED; 00727 } 00728 00729 return nsapiError; 00730 } 00731 00732 // Make a cellular connection 00733 nsapi_error_t UbloxATCellularInterfaceN2xx::connect(const char *sim_pin, 00734 const char *apn, 00735 const char *uname, 00736 const char *pwd) 00737 { 00738 nsapi_error_t nsapi_error; 00739 00740 if (sim_pin != NULL) { 00741 _pin = sim_pin; 00742 } 00743 00744 if (apn != NULL) { 00745 _apn = apn; 00746 } 00747 00748 if ((uname != NULL) && (pwd != NULL)) { 00749 _uname = uname; 00750 _pwd = pwd; 00751 } else { 00752 _uname = NULL; 00753 _pwd = NULL; 00754 } 00755 00756 tr_debug("SIM, APN, UName & pwd set, now calling connect()"); 00757 nsapi_error = connect(); 00758 00759 return nsapi_error; 00760 } 00761 00762 bool UbloxATCellularInterfaceN2xx::initialise() 00763 { 00764 return init(); 00765 } 00766 00767 // Make a cellular connection using the IP stack on board the cellular modem 00768 nsapi_error_t UbloxATCellularInterfaceN2xx::connect() 00769 { 00770 nsapi_error_t nsapi_error = NSAPI_ERROR_DEVICE_ERROR; 00771 bool registered = false; 00772 00773 // Set up modem and then register with the network 00774 if (initialise()) { 00775 00776 tr_debug("Trying to register..."); 00777 nsapi_error = NSAPI_ERROR_NO_CONNECTION; 00778 for (int retries = 0; !registered && (retries < 3); retries++) { 00779 if (nwk_registration()) { 00780 registered = true; 00781 } 00782 } 00783 } 00784 00785 // Attempt to establish a connection 00786 if (registered) { 00787 nsapi_error = NSAPI_ERROR_OK; 00788 } else { 00789 tr_debug("Failed to register."); 00790 } 00791 00792 return nsapi_error; 00793 } 00794 00795 // User initiated disconnect. 00796 nsapi_error_t UbloxATCellularInterfaceN2xx::disconnect() 00797 { 00798 nsapi_error_t nsapi_error = NSAPI_ERROR_DEVICE_ERROR; 00799 00800 if (nwk_deregistration()) { 00801 nsapi_error = NSAPI_ERROR_OK; 00802 00803 if (_connection_status_cb) { 00804 _connection_status_cb(NSAPI_ERROR_CONNECTION_LOST); 00805 } 00806 } 00807 00808 return nsapi_error; 00809 } 00810 00811 // Enable or disable SIM PIN check lock. 00812 nsapi_error_t UbloxATCellularInterfaceN2xx::set_sim_pin_check(bool set, 00813 bool immediate, 00814 const char *sim_pin) 00815 { 00816 return NSAPI_ERROR_UNSUPPORTED; 00817 } 00818 00819 // Change the PIN code for the SIM card. 00820 nsapi_error_t UbloxATCellularInterfaceN2xx::set_new_sim_pin(const char *new_pin, 00821 bool immediate, 00822 const char *old_pin) 00823 { 00824 return NSAPI_ERROR_UNSUPPORTED; 00825 } 00826 00827 // Determine if the connection is up. 00828 bool UbloxATCellularInterfaceN2xx::is_connected() 00829 { 00830 return get_ip_address() != NULL; 00831 } 00832 00833 // Get the IP address of the on-board modem IP stack. 00834 const char * UbloxATCellularInterfaceN2xx::get_ip_address() 00835 { 00836 SocketAddress address; 00837 int id; 00838 LOCK(); 00839 00840 if (_ip == NULL) 00841 { 00842 // Temporary storage for an IP address string with terminator 00843 _ip = (char *) malloc(NSAPI_IP_SIZE); 00844 } 00845 00846 if (_ip != NULL) { 00847 memset(_ip, 0, NSAPI_IP_SIZE); // Ensure a terminator 00848 // +CGPADDR - returns a list of IP Addresses per context, just pick the first one as SARA-N2xx only allows 1 context. 00849 if (!_at->send("AT+CGPADDR") || 00850 !_at->recv("+CGPADDR:%d,%15[^\n]\n", &id, _ip) || 00851 ! _at->recv("OK") || 00852 !address.set_ip_address(_ip) || 00853 !address) { 00854 free (_ip); 00855 _ip = NULL; 00856 } 00857 } 00858 00859 UNLOCK(); 00860 return _ip; 00861 } 00862 00863 // Get the local network mask. 00864 const char *UbloxATCellularInterfaceN2xx::get_netmask() 00865 { 00866 // Not implemented. 00867 return NULL; 00868 } 00869 00870 // Get the local gateways. 00871 const char *UbloxATCellularInterfaceN2xx::get_gateway() 00872 { 00873 return get_ip_address(); 00874 } 00875 00876 void UbloxATCellularInterfaceN2xx::set_LocalListenPort(int port) { 00877 _localListenPort = port; 00878 } 00879 00880 void UbloxATCellularInterfaceN2xx::set_plmn(const char *plmn) { 00881 00882 } 00883 00884 // Callback in case the connection is lost. 00885 void UbloxATCellularInterfaceN2xx::connection_status_cb(Callback<void(nsapi_error_t)> cb) 00886 { 00887 _connection_status_cb = cb; 00888 } 00889 00890 // End of file 00891
Generated on Thu Jul 14 2022 07:10:25 by
