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.
Fork of ublox-at-cellular-interface by
UbloxATCellularInterface.cpp@19:2e961ce171e6, 2018-09-27 (annotated)
- Committer:
- cblack
- Date:
- Thu Sep 27 15:45:38 2018 -0500
- Revision:
- 19:2e961ce171e6
- Parent:
- 18:bfc869299185
Fix to hex mode workaround - read 2x the size in hex mode
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| RobMeades | 0:7ccf0e7e8a83 | 1 | /* Copyright (c) 2017 ublox Limited |
| RobMeades | 0:7ccf0e7e8a83 | 2 | * |
| RobMeades | 0:7ccf0e7e8a83 | 3 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| RobMeades | 0:7ccf0e7e8a83 | 4 | * you may not use this file except in compliance with the License. |
| RobMeades | 0:7ccf0e7e8a83 | 5 | * You may obtain a copy of the License at |
| RobMeades | 0:7ccf0e7e8a83 | 6 | * |
| RobMeades | 0:7ccf0e7e8a83 | 7 | * http://www.apache.org/licenses/LICENSE-2.0 |
| RobMeades | 0:7ccf0e7e8a83 | 8 | * |
| RobMeades | 0:7ccf0e7e8a83 | 9 | * Unless required by applicable law or agreed to in writing, software |
| RobMeades | 0:7ccf0e7e8a83 | 10 | * distributed under the License is distributed on an "AS IS" BASIS, |
| RobMeades | 0:7ccf0e7e8a83 | 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| RobMeades | 0:7ccf0e7e8a83 | 12 | * See the License for the specific language governing permissions and |
| RobMeades | 0:7ccf0e7e8a83 | 13 | * limitations under the License. |
| RobMeades | 0:7ccf0e7e8a83 | 14 | */ |
| RobMeades | 0:7ccf0e7e8a83 | 15 | |
| RobMeades | 0:7ccf0e7e8a83 | 16 | #include "UbloxATCellularInterface.h" |
| RobMeades | 0:7ccf0e7e8a83 | 17 | #include "mbed_poll.h" |
| RobMeades | 0:7ccf0e7e8a83 | 18 | #include "nsapi.h" |
| RobMeades | 0:7ccf0e7e8a83 | 19 | #include "APN_db.h" |
| RobMeades | 0:7ccf0e7e8a83 | 20 | #ifdef FEATURE_COMMON_PAL |
| RobMeades | 0:7ccf0e7e8a83 | 21 | #include "mbed_trace.h" |
| RobMeades | 0:7ccf0e7e8a83 | 22 | #define TRACE_GROUP "UACI" |
| RobMeades | 0:7ccf0e7e8a83 | 23 | #else |
| rob.meades@u-blox.com | 5:f6706249d076 | 24 | #define tr_debug(format, ...) debug_if(_debug_trace_on, format "\n", ## __VA_ARGS__) |
| rob.meades@u-blox.com | 5:f6706249d076 | 25 | #define tr_info(format, ...) debug_if(_debug_trace_on, format "\n", ## __VA_ARGS__) |
| rob.meades@u-blox.com | 5:f6706249d076 | 26 | #define tr_warn(format, ...) debug_if(_debug_trace_on, format "\n", ## __VA_ARGS__) |
| rob.meades@u-blox.com | 5:f6706249d076 | 27 | #define tr_error(format, ...) debug_if(_debug_trace_on, format "\n", ## __VA_ARGS__) |
| RobMeades | 0:7ccf0e7e8a83 | 28 | #endif |
| RobMeades | 0:7ccf0e7e8a83 | 29 | |
| RobMeades | 0:7ccf0e7e8a83 | 30 | /********************************************************************** |
| RobMeades | 0:7ccf0e7e8a83 | 31 | * PRIVATE METHODS |
| RobMeades | 0:7ccf0e7e8a83 | 32 | **********************************************************************/ |
| RobMeades | 0:7ccf0e7e8a83 | 33 | |
| RobMeades | 0:7ccf0e7e8a83 | 34 | // Event thread for asynchronous received data handling. |
| RobMeades | 0:7ccf0e7e8a83 | 35 | void UbloxATCellularInterface::handle_event(){ |
| RobMeades | 0:7ccf0e7e8a83 | 36 | pollfh fhs; |
| RobMeades | 0:7ccf0e7e8a83 | 37 | int count; |
| RobMeades | 0:7ccf0e7e8a83 | 38 | int at_timeout; |
| RobMeades | 0:7ccf0e7e8a83 | 39 | |
| RobMeades | 0:7ccf0e7e8a83 | 40 | fhs.fh = _fh; |
| RobMeades | 0:7ccf0e7e8a83 | 41 | fhs.events = POLLIN; |
| RobMeades | 0:7ccf0e7e8a83 | 42 | |
| RobMeades | 14:e7dcf3388403 | 43 | while (_run_event_thread) { |
| RobMeades | 0:7ccf0e7e8a83 | 44 | count = poll(&fhs, 1, 1000); |
| RobMeades | 0:7ccf0e7e8a83 | 45 | if (count > 0 && (fhs.revents & POLLIN)) { |
| RobMeades | 0:7ccf0e7e8a83 | 46 | LOCK(); |
| RobMeades | 0:7ccf0e7e8a83 | 47 | at_timeout = _at_timeout; |
| RobMeades | 0:7ccf0e7e8a83 | 48 | at_set_timeout(10); // Avoid blocking but also make sure we don't |
| Curt Black |
18:bfc869299185 | 49 | // time out if we get ahead of the serial port |
| RobMeades | 0:7ccf0e7e8a83 | 50 | _at->debug_on(false); // Debug here screws with the test output |
| RobMeades | 0:7ccf0e7e8a83 | 51 | // Let the URCs run |
| RobMeades | 0:7ccf0e7e8a83 | 52 | _at->recv(UNNATURAL_STRING); |
| RobMeades | 0:7ccf0e7e8a83 | 53 | _at->debug_on(_debug_trace_on); |
| RobMeades | 0:7ccf0e7e8a83 | 54 | at_set_timeout(at_timeout); |
| RobMeades | 0:7ccf0e7e8a83 | 55 | UNLOCK(); |
| RobMeades | 0:7ccf0e7e8a83 | 56 | } |
| RobMeades | 0:7ccf0e7e8a83 | 57 | } |
| RobMeades | 0:7ccf0e7e8a83 | 58 | } |
| RobMeades | 0:7ccf0e7e8a83 | 59 | |
| RobMeades | 0:7ccf0e7e8a83 | 60 | // Find or create a socket from the list. |
| RobMeades | 0:7ccf0e7e8a83 | 61 | UbloxATCellularInterface::SockCtrl * UbloxATCellularInterface::find_socket(int modem_handle) |
| RobMeades | 0:7ccf0e7e8a83 | 62 | { |
| RobMeades | 0:7ccf0e7e8a83 | 63 | UbloxATCellularInterface::SockCtrl *socket = NULL; |
| RobMeades | 0:7ccf0e7e8a83 | 64 | |
| RobMeades | 0:7ccf0e7e8a83 | 65 | for (unsigned int x = 0; (socket == NULL) && (x < sizeof(_sockets) / sizeof(_sockets[0])); x++) { |
| RobMeades | 0:7ccf0e7e8a83 | 66 | if (_sockets[x].modem_handle == modem_handle) { |
| RobMeades | 0:7ccf0e7e8a83 | 67 | socket = &(_sockets[x]); |
| RobMeades | 0:7ccf0e7e8a83 | 68 | } |
| RobMeades | 0:7ccf0e7e8a83 | 69 | } |
| RobMeades | 0:7ccf0e7e8a83 | 70 | |
| RobMeades | 0:7ccf0e7e8a83 | 71 | return socket; |
| RobMeades | 0:7ccf0e7e8a83 | 72 | } |
| RobMeades | 0:7ccf0e7e8a83 | 73 | |
| RobMeades | 0:7ccf0e7e8a83 | 74 | // Clear out the storage for a socket |
| RobMeades | 0:7ccf0e7e8a83 | 75 | void UbloxATCellularInterface::clear_socket(UbloxATCellularInterface::SockCtrl * socket) |
| RobMeades | 0:7ccf0e7e8a83 | 76 | { |
| RobMeades | 0:7ccf0e7e8a83 | 77 | if (socket != NULL) { |
| RobMeades | 0:7ccf0e7e8a83 | 78 | socket->modem_handle = SOCKET_UNUSED; |
| RobMeades | 0:7ccf0e7e8a83 | 79 | socket->pending = 0; |
| RobMeades | 0:7ccf0e7e8a83 | 80 | socket->callback = NULL; |
| RobMeades | 0:7ccf0e7e8a83 | 81 | socket->data = NULL; |
| RobMeades | 0:7ccf0e7e8a83 | 82 | } |
| RobMeades | 0:7ccf0e7e8a83 | 83 | } |
| RobMeades | 0:7ccf0e7e8a83 | 84 | |
| RobMeades | 0:7ccf0e7e8a83 | 85 | // Check that a socket pointer is valid |
| RobMeades | 0:7ccf0e7e8a83 | 86 | bool UbloxATCellularInterface::check_socket(SockCtrl * socket) |
| RobMeades | 0:7ccf0e7e8a83 | 87 | { |
| RobMeades | 0:7ccf0e7e8a83 | 88 | bool success = false; |
| RobMeades | 0:7ccf0e7e8a83 | 89 | |
| RobMeades | 0:7ccf0e7e8a83 | 90 | if (socket != NULL) { |
| RobMeades | 0:7ccf0e7e8a83 | 91 | for (unsigned int x = 0; !success && (x < sizeof(_sockets) / sizeof(_sockets[0])); x++) { |
| RobMeades | 0:7ccf0e7e8a83 | 92 | if (socket == &(_sockets[x])) { |
| RobMeades | 0:7ccf0e7e8a83 | 93 | success = true; |
| RobMeades | 0:7ccf0e7e8a83 | 94 | } |
| RobMeades | 0:7ccf0e7e8a83 | 95 | } |
| RobMeades | 0:7ccf0e7e8a83 | 96 | } |
| RobMeades | 0:7ccf0e7e8a83 | 97 | |
| RobMeades | 0:7ccf0e7e8a83 | 98 | return success; |
| RobMeades | 0:7ccf0e7e8a83 | 99 | } |
| RobMeades | 0:7ccf0e7e8a83 | 100 | |
| RobMeades | 0:7ccf0e7e8a83 | 101 | // Convert nsapi_security_t to the modem security numbers |
| RobMeades | 0:7ccf0e7e8a83 | 102 | int UbloxATCellularInterface::nsapi_security_to_modem_security(nsapi_security_t nsapi_security) |
| RobMeades | 0:7ccf0e7e8a83 | 103 | { |
| RobMeades | 0:7ccf0e7e8a83 | 104 | int modem_security = 3; |
| RobMeades | 0:7ccf0e7e8a83 | 105 | |
| RobMeades | 0:7ccf0e7e8a83 | 106 | switch (nsapi_security) |
| RobMeades | 0:7ccf0e7e8a83 | 107 | { |
| Curt Black |
18:bfc869299185 | 108 | case NSAPI_SECURITY_NONE: |
| Curt Black |
18:bfc869299185 | 109 | modem_security = 0; |
| Curt Black |
18:bfc869299185 | 110 | break; |
| Curt Black |
18:bfc869299185 | 111 | case NSAPI_SECURITY_PAP: |
| Curt Black |
18:bfc869299185 | 112 | modem_security = 1; |
| Curt Black |
18:bfc869299185 | 113 | break; |
| Curt Black |
18:bfc869299185 | 114 | case NSAPI_SECURITY_CHAP: |
| Curt Black |
18:bfc869299185 | 115 | modem_security = 2; |
| Curt Black |
18:bfc869299185 | 116 | break; |
| Curt Black |
18:bfc869299185 | 117 | case NSAPI_SECURITY_UNKNOWN: |
| Curt Black |
18:bfc869299185 | 118 | modem_security = 3; |
| Curt Black |
18:bfc869299185 | 119 | break; |
| Curt Black |
18:bfc869299185 | 120 | default: |
| Curt Black |
18:bfc869299185 | 121 | modem_security = 3; |
| Curt Black |
18:bfc869299185 | 122 | break; |
| RobMeades | 0:7ccf0e7e8a83 | 123 | } |
| RobMeades | 0:7ccf0e7e8a83 | 124 | |
| RobMeades | 0:7ccf0e7e8a83 | 125 | return modem_security; |
| RobMeades | 0:7ccf0e7e8a83 | 126 | } |
| RobMeades | 0:7ccf0e7e8a83 | 127 | |
| RobMeades | 0:7ccf0e7e8a83 | 128 | // Callback for Socket Read URC. |
| RobMeades | 0:7ccf0e7e8a83 | 129 | void UbloxATCellularInterface::UUSORD_URC() |
| RobMeades | 0:7ccf0e7e8a83 | 130 | { |
| RobMeades | 0:7ccf0e7e8a83 | 131 | int a; |
| RobMeades | 0:7ccf0e7e8a83 | 132 | int b; |
| RobMeades | 0:7ccf0e7e8a83 | 133 | char buf[32]; |
| RobMeades | 0:7ccf0e7e8a83 | 134 | SockCtrl *socket; |
| RobMeades | 0:7ccf0e7e8a83 | 135 | |
| RobMeades | 0:7ccf0e7e8a83 | 136 | // Note: not calling _at->recv() from here as we're |
| RobMeades | 0:7ccf0e7e8a83 | 137 | // already in an _at->recv() |
| RobMeades | 0:7ccf0e7e8a83 | 138 | // +UUSORD: <socket>,<length> |
| RobMeades | 0:7ccf0e7e8a83 | 139 | if (read_at_to_char(buf, sizeof (buf), '\n') > 0) { |
| RobMeades | 0:7ccf0e7e8a83 | 140 | if (sscanf(buf, ": %d,%d", &a, &b) == 2) { |
| RobMeades | 0:7ccf0e7e8a83 | 141 | socket = find_socket(a); |
| RobMeades | 0:7ccf0e7e8a83 | 142 | if (socket != NULL) { |
| RobMeades | 0:7ccf0e7e8a83 | 143 | socket->pending = b; |
| RobMeades | 0:7ccf0e7e8a83 | 144 | // No debug prints here as they can affect timing |
| RobMeades | 0:7ccf0e7e8a83 | 145 | // and cause data loss in UARTSerial |
| RobMeades | 0:7ccf0e7e8a83 | 146 | if (socket->callback != NULL) { |
| RobMeades | 0:7ccf0e7e8a83 | 147 | socket->callback(socket->data); |
| RobMeades | 0:7ccf0e7e8a83 | 148 | } |
| RobMeades | 0:7ccf0e7e8a83 | 149 | } |
| RobMeades | 0:7ccf0e7e8a83 | 150 | } |
| RobMeades | 0:7ccf0e7e8a83 | 151 | } |
| RobMeades | 0:7ccf0e7e8a83 | 152 | } |
| RobMeades | 0:7ccf0e7e8a83 | 153 | |
| RobMeades | 0:7ccf0e7e8a83 | 154 | // Callback for Socket Read From URC. |
| RobMeades | 0:7ccf0e7e8a83 | 155 | void UbloxATCellularInterface::UUSORF_URC() |
| RobMeades | 0:7ccf0e7e8a83 | 156 | { |
| RobMeades | 0:7ccf0e7e8a83 | 157 | int a; |
| RobMeades | 0:7ccf0e7e8a83 | 158 | int b; |
| RobMeades | 0:7ccf0e7e8a83 | 159 | char buf[32]; |
| RobMeades | 0:7ccf0e7e8a83 | 160 | SockCtrl *socket; |
| RobMeades | 0:7ccf0e7e8a83 | 161 | |
| RobMeades | 0:7ccf0e7e8a83 | 162 | // Note: not calling _at->recv() from here as we're |
| RobMeades | 0:7ccf0e7e8a83 | 163 | // already in an _at->recv() |
| RobMeades | 0:7ccf0e7e8a83 | 164 | // +UUSORF: <socket>,<length> |
| RobMeades | 0:7ccf0e7e8a83 | 165 | if (read_at_to_char(buf, sizeof (buf), '\n') > 0) { |
| RobMeades | 0:7ccf0e7e8a83 | 166 | if (sscanf(buf, ": %d,%d", &a, &b) == 2) { |
| RobMeades | 0:7ccf0e7e8a83 | 167 | socket = find_socket(a); |
| RobMeades | 0:7ccf0e7e8a83 | 168 | if (socket != NULL) { |
| RobMeades | 0:7ccf0e7e8a83 | 169 | socket->pending = b; |
| RobMeades | 0:7ccf0e7e8a83 | 170 | // No debug prints here as they can affect timing |
| RobMeades | 0:7ccf0e7e8a83 | 171 | // and cause data loss in UARTSerial |
| RobMeades | 0:7ccf0e7e8a83 | 172 | if (socket->callback != NULL) { |
| RobMeades | 0:7ccf0e7e8a83 | 173 | socket->callback(socket->data); |
| RobMeades | 0:7ccf0e7e8a83 | 174 | } |
| RobMeades | 0:7ccf0e7e8a83 | 175 | } |
| RobMeades | 0:7ccf0e7e8a83 | 176 | } |
| RobMeades | 0:7ccf0e7e8a83 | 177 | } |
| RobMeades | 0:7ccf0e7e8a83 | 178 | } |
| RobMeades | 0:7ccf0e7e8a83 | 179 | |
| RobMeades | 0:7ccf0e7e8a83 | 180 | // Callback for Socket Close URC. |
| RobMeades | 0:7ccf0e7e8a83 | 181 | void UbloxATCellularInterface::UUSOCL_URC() |
| RobMeades | 0:7ccf0e7e8a83 | 182 | { |
| RobMeades | 0:7ccf0e7e8a83 | 183 | int a; |
| RobMeades | 0:7ccf0e7e8a83 | 184 | char buf[32]; |
| RobMeades | 0:7ccf0e7e8a83 | 185 | SockCtrl *socket; |
| RobMeades | 0:7ccf0e7e8a83 | 186 | |
| RobMeades | 0:7ccf0e7e8a83 | 187 | // Note: not calling _at->recv() from here as we're |
| RobMeades | 0:7ccf0e7e8a83 | 188 | // already in an _at->recv() |
| RobMeades | 0:7ccf0e7e8a83 | 189 | // +UUSOCL: <socket> |
| RobMeades | 0:7ccf0e7e8a83 | 190 | if (read_at_to_char(buf, sizeof (buf), '\n') > 0) { |
| RobMeades | 0:7ccf0e7e8a83 | 191 | if (sscanf(buf, ": %d", &a) == 1) { |
| RobMeades | 0:7ccf0e7e8a83 | 192 | socket = find_socket(a); |
| RobMeades | 0:7ccf0e7e8a83 | 193 | tr_debug("Socket 0x%08x: handle %d closed by remote host", |
| Curt Black |
18:bfc869299185 | 194 | (unsigned int) socket, a); |
| RobMeades | 0:7ccf0e7e8a83 | 195 | clear_socket(socket); |
| RobMeades | 0:7ccf0e7e8a83 | 196 | } |
| RobMeades | 0:7ccf0e7e8a83 | 197 | } |
| RobMeades | 0:7ccf0e7e8a83 | 198 | } |
| RobMeades | 0:7ccf0e7e8a83 | 199 | |
| RobMeades | 0:7ccf0e7e8a83 | 200 | // Callback for UUPSDD. |
| RobMeades | 0:7ccf0e7e8a83 | 201 | void UbloxATCellularInterface::UUPSDD_URC() |
| RobMeades | 0:7ccf0e7e8a83 | 202 | { |
| RobMeades | 0:7ccf0e7e8a83 | 203 | int a; |
| RobMeades | 0:7ccf0e7e8a83 | 204 | char buf[32]; |
| RobMeades | 0:7ccf0e7e8a83 | 205 | SockCtrl *socket; |
| RobMeades | 0:7ccf0e7e8a83 | 206 | |
| RobMeades | 0:7ccf0e7e8a83 | 207 | // Note: not calling _at->recv() from here as we're |
| RobMeades | 0:7ccf0e7e8a83 | 208 | // already in an _at->recv() |
| RobMeades | 0:7ccf0e7e8a83 | 209 | // +UUPSDD: <socket> |
| RobMeades | 0:7ccf0e7e8a83 | 210 | if (read_at_to_char(buf, sizeof (buf), '\n') > 0) { |
| RobMeades | 0:7ccf0e7e8a83 | 211 | if (sscanf(buf, ": %d", &a) == 1) { |
| RobMeades | 0:7ccf0e7e8a83 | 212 | socket = find_socket(a); |
| RobMeades | 0:7ccf0e7e8a83 | 213 | tr_debug("Socket 0x%08x: handle %d connection lost", |
| Curt Black |
18:bfc869299185 | 214 | (unsigned int) socket, a); |
| RobMeades | 0:7ccf0e7e8a83 | 215 | clear_socket(socket); |
| RobMeades | 0:7ccf0e7e8a83 | 216 | if (_connection_status_cb) { |
| RobMeades | 0:7ccf0e7e8a83 | 217 | _connection_status_cb(NSAPI_ERROR_CONNECTION_LOST); |
| RobMeades | 0:7ccf0e7e8a83 | 218 | } |
| RobMeades | 0:7ccf0e7e8a83 | 219 | } |
| RobMeades | 0:7ccf0e7e8a83 | 220 | } |
| RobMeades | 0:7ccf0e7e8a83 | 221 | } |
| RobMeades | 0:7ccf0e7e8a83 | 222 | |
| RobMeades | 0:7ccf0e7e8a83 | 223 | /********************************************************************** |
| RobMeades | 0:7ccf0e7e8a83 | 224 | * PROTECTED METHODS: GENERAL |
| RobMeades | 0:7ccf0e7e8a83 | 225 | **********************************************************************/ |
| RobMeades | 0:7ccf0e7e8a83 | 226 | |
| RobMeades | 0:7ccf0e7e8a83 | 227 | // Get the next set of credentials, based on IMSI. |
| rob.meades@u-blox.com | 7:3b2ca10cc23a | 228 | void UbloxATCellularInterface::get_next_credentials(const char ** config) |
| RobMeades | 0:7ccf0e7e8a83 | 229 | { |
| rob.meades@u-blox.com | 7:3b2ca10cc23a | 230 | if (*config) { |
| rob.meades@u-blox.com | 7:3b2ca10cc23a | 231 | _apn = _APN_GET(*config); |
| rob.meades@u-blox.com | 7:3b2ca10cc23a | 232 | _uname = _APN_GET(*config); |
| rob.meades@u-blox.com | 7:3b2ca10cc23a | 233 | _pwd = _APN_GET(*config); |
| RobMeades | 0:7ccf0e7e8a83 | 234 | } |
| RobMeades | 0:7ccf0e7e8a83 | 235 | |
| RobMeades | 0:7ccf0e7e8a83 | 236 | _apn = _apn ? _apn : ""; |
| RobMeades | 0:7ccf0e7e8a83 | 237 | _uname = _uname ? _uname : ""; |
| RobMeades | 0:7ccf0e7e8a83 | 238 | _pwd = _pwd ? _pwd : ""; |
| RobMeades | 0:7ccf0e7e8a83 | 239 | } |
| RobMeades | 0:7ccf0e7e8a83 | 240 | |
| RobMeades | 0:7ccf0e7e8a83 | 241 | // Active a connection profile on board the modem. |
| RobMeades | 0:7ccf0e7e8a83 | 242 | // Note: the AT interface should be locked before this is called. |
| RobMeades | 0:7ccf0e7e8a83 | 243 | bool UbloxATCellularInterface::activate_profile(const char* apn, |
| Curt Black |
18:bfc869299185 | 244 | const char* username, |
| Curt Black |
18:bfc869299185 | 245 | const char* password, |
| Curt Black |
18:bfc869299185 | 246 | nsapi_security_t auth) |
| RobMeades | 0:7ccf0e7e8a83 | 247 | { |
| RobMeades | 0:7ccf0e7e8a83 | 248 | bool activated = false; |
| RobMeades | 0:7ccf0e7e8a83 | 249 | bool success = false; |
| RobMeades | 0:7ccf0e7e8a83 | 250 | int at_timeout = _at_timeout; |
| RobMeades | 0:7ccf0e7e8a83 | 251 | SocketAddress address; |
| RobMeades | 0:7ccf0e7e8a83 | 252 | |
| RobMeades | 0:7ccf0e7e8a83 | 253 | // Set up the APN |
| RobMeades | 0:7ccf0e7e8a83 | 254 | if (*apn) { |
| RobMeades | 0:7ccf0e7e8a83 | 255 | success = _at->send("AT+UPSD=" PROFILE ",1,\"%s\"", apn) && _at->recv("OK"); |
| RobMeades | 0:7ccf0e7e8a83 | 256 | } |
| RobMeades | 0:7ccf0e7e8a83 | 257 | if (success && *username) { |
| RobMeades | 0:7ccf0e7e8a83 | 258 | success = _at->send("AT+UPSD=" PROFILE ",2,\"%s\"", username) && _at->recv("OK"); |
| RobMeades | 0:7ccf0e7e8a83 | 259 | } |
| RobMeades | 0:7ccf0e7e8a83 | 260 | if (success && *password) { |
| RobMeades | 0:7ccf0e7e8a83 | 261 | success = _at->send("AT+UPSD=" PROFILE ",3,\"%s\"", password) && _at->recv("OK"); |
| RobMeades | 0:7ccf0e7e8a83 | 262 | } |
| RobMeades | 0:7ccf0e7e8a83 | 263 | |
| RobMeades | 0:7ccf0e7e8a83 | 264 | if (success) { |
| RobMeades | 0:7ccf0e7e8a83 | 265 | // Set up dynamic IP address assignment. |
| RobMeades | 0:7ccf0e7e8a83 | 266 | success = _at->send("AT+UPSD=" PROFILE ",7,\"0.0.0.0\"") && _at->recv("OK"); |
| RobMeades | 0:7ccf0e7e8a83 | 267 | // Set up the authentication protocol |
| RobMeades | 0:7ccf0e7e8a83 | 268 | // 0 = none |
| RobMeades | 0:7ccf0e7e8a83 | 269 | // 1 = PAP (Password Authentication Protocol) |
| RobMeades | 0:7ccf0e7e8a83 | 270 | // 2 = CHAP (Challenge Handshake Authentication Protocol) |
| RobMeades | 0:7ccf0e7e8a83 | 271 | for (int protocol = nsapi_security_to_modem_security(NSAPI_SECURITY_NONE); |
| Curt Black |
18:bfc869299185 | 272 | success && (protocol <= nsapi_security_to_modem_security(NSAPI_SECURITY_CHAP)); protocol++) { |
| RobMeades | 0:7ccf0e7e8a83 | 273 | if ((_auth == NSAPI_SECURITY_UNKNOWN) || (nsapi_security_to_modem_security(_auth) == protocol)) { |
| RobMeades | 0:7ccf0e7e8a83 | 274 | if (_at->send("AT+UPSD=" PROFILE ",6,%d", protocol) && _at->recv("OK")) { |
| RobMeades | 0:7ccf0e7e8a83 | 275 | // Activate, waiting 30 seconds for the connection to be made |
| RobMeades | 0:7ccf0e7e8a83 | 276 | at_set_timeout(30000); |
| RobMeades | 0:7ccf0e7e8a83 | 277 | activated = _at->send("AT+UPSDA=" PROFILE ",3") && _at->recv("OK"); |
| RobMeades | 0:7ccf0e7e8a83 | 278 | at_set_timeout(at_timeout); |
| RobMeades | 0:7ccf0e7e8a83 | 279 | } |
| RobMeades | 0:7ccf0e7e8a83 | 280 | } |
| RobMeades | 0:7ccf0e7e8a83 | 281 | } |
| RobMeades | 0:7ccf0e7e8a83 | 282 | } |
| RobMeades | 0:7ccf0e7e8a83 | 283 | |
| RobMeades | 0:7ccf0e7e8a83 | 284 | return activated; |
| RobMeades | 0:7ccf0e7e8a83 | 285 | } |
| RobMeades | 0:7ccf0e7e8a83 | 286 | |
| RobMeades | 0:7ccf0e7e8a83 | 287 | // Activate a profile by reusing an external PDP context. |
| RobMeades | 0:7ccf0e7e8a83 | 288 | // Note: the AT interface should be locked before this is called. |
| RobMeades | 0:7ccf0e7e8a83 | 289 | bool UbloxATCellularInterface::activate_profile_reuse_external(void) |
| RobMeades | 0:7ccf0e7e8a83 | 290 | { |
| RobMeades | 0:7ccf0e7e8a83 | 291 | bool success = false; |
| RobMeades | 0:7ccf0e7e8a83 | 292 | int cid = -1; |
| RobMeades | 0:7ccf0e7e8a83 | 293 | char ip[NSAPI_IP_SIZE]; |
| RobMeades | 0:7ccf0e7e8a83 | 294 | SocketAddress address; |
| RobMeades | 0:7ccf0e7e8a83 | 295 | int t; |
| RobMeades | 0:7ccf0e7e8a83 | 296 | int at_timeout = _at_timeout; |
| RobMeades | 0:7ccf0e7e8a83 | 297 | |
| RobMeades | 0:7ccf0e7e8a83 | 298 | //+CGDCONT: <cid>,"IP","<apn name>","<ip adr>",0,0,0,0,0,0 |
| RobMeades | 0:7ccf0e7e8a83 | 299 | if (_at->send("AT+CGDCONT?")) { |
| RobMeades | 0:7ccf0e7e8a83 | 300 | if (_at->recv("+CGDCONT: %d,\"IP\",\"%*[^\"]\",\"%" u_stringify(NSAPI_IP_SIZE) "[^\"]\",%*d,%*d,%*d,%*d,%*d,%*d", |
| Curt Black |
18:bfc869299185 | 301 | &t, ip) && |
| Curt Black |
18:bfc869299185 | 302 | _at->recv("OK")) { |
| RobMeades | 0:7ccf0e7e8a83 | 303 | // Check if the IP address is valid |
| RobMeades | 0:7ccf0e7e8a83 | 304 | if (address.set_ip_address(ip)) { |
| RobMeades | 0:7ccf0e7e8a83 | 305 | cid = t; |
| RobMeades | 0:7ccf0e7e8a83 | 306 | } |
| RobMeades | 0:7ccf0e7e8a83 | 307 | } |
| RobMeades | 0:7ccf0e7e8a83 | 308 | } |
| RobMeades | 0:7ccf0e7e8a83 | 309 | |
| RobMeades | 0:7ccf0e7e8a83 | 310 | // If a context has been found, use it |
| RobMeades | 0:7ccf0e7e8a83 | 311 | if ((cid != -1) && (_at->send("AT+UPSD=" PROFILE ",100,%d", cid) && _at->recv("OK"))) { |
| RobMeades | 0:7ccf0e7e8a83 | 312 | // Activate, waiting 30 seconds for the connection to be made |
| RobMeades | 0:7ccf0e7e8a83 | 313 | at_set_timeout(30000); |
| RobMeades | 0:7ccf0e7e8a83 | 314 | success = _at->send("AT+UPSDA=" PROFILE ",3") && _at->recv("OK"); |
| RobMeades | 0:7ccf0e7e8a83 | 315 | at_set_timeout(at_timeout); |
| RobMeades | 0:7ccf0e7e8a83 | 316 | } |
| RobMeades | 0:7ccf0e7e8a83 | 317 | |
| RobMeades | 0:7ccf0e7e8a83 | 318 | return success; |
| RobMeades | 0:7ccf0e7e8a83 | 319 | } |
| RobMeades | 0:7ccf0e7e8a83 | 320 | |
| RobMeades | 0:7ccf0e7e8a83 | 321 | // Activate a profile by context ID. |
| RobMeades | 0:7ccf0e7e8a83 | 322 | // Note: the AT interface should be locked before this is called. |
| RobMeades | 0:7ccf0e7e8a83 | 323 | bool UbloxATCellularInterface::activate_profile_by_cid(int cid, |
| Curt Black |
18:bfc869299185 | 324 | const char* apn, |
| Curt Black |
18:bfc869299185 | 325 | const char* username, |
| Curt Black |
18:bfc869299185 | 326 | const char* password, |
| Curt Black |
18:bfc869299185 | 327 | nsapi_security_t auth) |
| RobMeades | 0:7ccf0e7e8a83 | 328 | { |
| RobMeades | 0:7ccf0e7e8a83 | 329 | bool success = false; |
| RobMeades | 0:7ccf0e7e8a83 | 330 | int at_timeout = _at_timeout; |
| RobMeades | 0:7ccf0e7e8a83 | 331 | |
| cblack | 16:da7f7b30c3de | 332 | // Must be detached to change CGDCONT |
| cblack | 16:da7f7b30c3de | 333 | if (_at->send("AT+CGATT=0") && _at->recv("OK")) { |
| cblack | 16:da7f7b30c3de | 334 | if (_at->send("AT+CGDCONT=%d,\"IP\",\"%s\"", cid, apn) && _at->recv("OK") && |
| Curt Black |
18:bfc869299185 | 335 | _at->send("AT+UAUTHREQ=%d,%d,\"%s\",\"%s\"", cid, nsapi_security_to_modem_security(auth), |
| Curt Black |
18:bfc869299185 | 336 | username, password) && _at->recv("OK") && |
| Curt Black |
18:bfc869299185 | 337 | _at->send("AT+UPSD=" PROFILE ",100,%d", cid) && _at->recv("OK")) { |
| RobMeades | 0:7ccf0e7e8a83 | 338 | |
| cblack | 16:da7f7b30c3de | 339 | // Wait 30 seconds for the connection to be made |
| cblack | 16:da7f7b30c3de | 340 | at_set_timeout(30000); |
| cblack | 16:da7f7b30c3de | 341 | // Activate the protocol |
| cblack | 16:da7f7b30c3de | 342 | success = _at->send("AT+UPSDA=" PROFILE ",3") && _at->recv("OK"); |
| cblack | 16:da7f7b30c3de | 343 | at_set_timeout(at_timeout); |
| cblack | 16:da7f7b30c3de | 344 | } |
| RobMeades | 0:7ccf0e7e8a83 | 345 | } |
| RobMeades | 0:7ccf0e7e8a83 | 346 | |
| RobMeades | 0:7ccf0e7e8a83 | 347 | return success; |
| RobMeades | 0:7ccf0e7e8a83 | 348 | } |
| RobMeades | 0:7ccf0e7e8a83 | 349 | |
| RobMeades | 0:7ccf0e7e8a83 | 350 | // Connect the on board IP stack of the modem. |
| RobMeades | 0:7ccf0e7e8a83 | 351 | bool UbloxATCellularInterface::connect_modem_stack() |
| RobMeades | 0:7ccf0e7e8a83 | 352 | { |
| RobMeades | 0:7ccf0e7e8a83 | 353 | bool success = false; |
| RobMeades | 0:7ccf0e7e8a83 | 354 | int active = 0; |
| RobMeades | 0:7ccf0e7e8a83 | 355 | const char * config = NULL; |
| RobMeades | 0:7ccf0e7e8a83 | 356 | LOCK(); |
| RobMeades | 0:7ccf0e7e8a83 | 357 | |
| RobMeades | 0:7ccf0e7e8a83 | 358 | // Check the profile |
| RobMeades | 0:7ccf0e7e8a83 | 359 | if (_at->send("AT+UPSND=" PROFILE ",8") && _at->recv("+UPSND: %*d,%*d,%d\n", &active) && |
| Curt Black |
18:bfc869299185 | 360 | _at->recv("OK")) { |
| RobMeades | 0:7ccf0e7e8a83 | 361 | if (active == 0) { |
| RobMeades | 0:7ccf0e7e8a83 | 362 | // If the caller hasn't entered an APN, try to find it |
| RobMeades | 0:7ccf0e7e8a83 | 363 | if (_apn == NULL) { |
| RobMeades | 0:7ccf0e7e8a83 | 364 | config = apnconfig(_dev_info.imsi); |
| RobMeades | 0:7ccf0e7e8a83 | 365 | } |
| RobMeades | 0:7ccf0e7e8a83 | 366 | |
| RobMeades | 0:7ccf0e7e8a83 | 367 | // Attempt to connect |
| RobMeades | 0:7ccf0e7e8a83 | 368 | do { |
| RobMeades | 0:7ccf0e7e8a83 | 369 | // Set up APN and IP protocol for PDP context |
| rob.meades@u-blox.com | 7:3b2ca10cc23a | 370 | get_next_credentials(&config); |
| RobMeades | 0:7ccf0e7e8a83 | 371 | _auth = (*_uname && *_pwd) ? _auth : NSAPI_SECURITY_NONE; |
| cblack | 16:da7f7b30c3de | 372 | // TOBY-L2 / MPCI-L2 / LARA-R2 / TOBY-R2 mapped to <cid> via param tag 100 |
| cblack | 16:da7f7b30c3de | 373 | if ((_dev_info.dev != DEV_TOBY_L2) && (_dev_info.dev != DEV_MPCI_L2) && (_dev_info.dev != DEV_LARA_R2)) { |
| RobMeades | 0:7ccf0e7e8a83 | 374 | success = activate_profile(_apn, _uname, _pwd, _auth); |
| RobMeades | 0:7ccf0e7e8a83 | 375 | } else { |
| RobMeades | 0:7ccf0e7e8a83 | 376 | success = activate_profile_reuse_external(); |
| RobMeades | 0:7ccf0e7e8a83 | 377 | if (success) { |
| RobMeades | 0:7ccf0e7e8a83 | 378 | tr_debug("Reusing external context"); |
| RobMeades | 0:7ccf0e7e8a83 | 379 | } else { |
| RobMeades | 0:7ccf0e7e8a83 | 380 | success = activate_profile_by_cid(1, _apn, _uname, _pwd, _auth); |
| RobMeades | 0:7ccf0e7e8a83 | 381 | } |
| RobMeades | 0:7ccf0e7e8a83 | 382 | } |
| RobMeades | 0:7ccf0e7e8a83 | 383 | } while (!success && config && *config); |
| RobMeades | 0:7ccf0e7e8a83 | 384 | } else { |
| RobMeades | 0:7ccf0e7e8a83 | 385 | // If the profile is already active, we're good |
| RobMeades | 0:7ccf0e7e8a83 | 386 | success = true; |
| RobMeades | 0:7ccf0e7e8a83 | 387 | } |
| RobMeades | 0:7ccf0e7e8a83 | 388 | } |
| RobMeades | 0:7ccf0e7e8a83 | 389 | |
| RobMeades | 0:7ccf0e7e8a83 | 390 | if (!success) { |
| RobMeades | 0:7ccf0e7e8a83 | 391 | tr_error("Failed to connect, check your APN/username/password"); |
| RobMeades | 0:7ccf0e7e8a83 | 392 | } |
| RobMeades | 0:7ccf0e7e8a83 | 393 | |
| RobMeades | 0:7ccf0e7e8a83 | 394 | UNLOCK(); |
| RobMeades | 0:7ccf0e7e8a83 | 395 | return success; |
| RobMeades | 0:7ccf0e7e8a83 | 396 | } |
| RobMeades | 0:7ccf0e7e8a83 | 397 | |
| RobMeades | 0:7ccf0e7e8a83 | 398 | // Disconnect the on board IP stack of the modem. |
| RobMeades | 0:7ccf0e7e8a83 | 399 | bool UbloxATCellularInterface::disconnect_modem_stack() |
| RobMeades | 0:7ccf0e7e8a83 | 400 | { |
| RobMeades | 0:7ccf0e7e8a83 | 401 | bool success = false; |
| RobMeades | 0:7ccf0e7e8a83 | 402 | LOCK(); |
| RobMeades | 0:7ccf0e7e8a83 | 403 | |
| RobMeades | 0:7ccf0e7e8a83 | 404 | if (get_ip_address() != NULL) { |
| RobMeades | 0:7ccf0e7e8a83 | 405 | if (_at->send("AT+UPSDA=" PROFILE ",4") && _at->recv("OK")) { |
| RobMeades | 0:7ccf0e7e8a83 | 406 | success = true; |
| RobMeades | 0:7ccf0e7e8a83 | 407 | if (_connection_status_cb) { |
| RobMeades | 0:7ccf0e7e8a83 | 408 | _connection_status_cb(NSAPI_ERROR_CONNECTION_LOST); |
| RobMeades | 0:7ccf0e7e8a83 | 409 | } |
| RobMeades | 0:7ccf0e7e8a83 | 410 | } |
| RobMeades | 0:7ccf0e7e8a83 | 411 | } |
| RobMeades | 0:7ccf0e7e8a83 | 412 | |
| RobMeades | 0:7ccf0e7e8a83 | 413 | UNLOCK(); |
| RobMeades | 0:7ccf0e7e8a83 | 414 | return success; |
| RobMeades | 0:7ccf0e7e8a83 | 415 | } |
| RobMeades | 0:7ccf0e7e8a83 | 416 | |
| RobMeades | 0:7ccf0e7e8a83 | 417 | /********************************************************************** |
| RobMeades | 0:7ccf0e7e8a83 | 418 | * PROTECTED METHODS: NETWORK INTERFACE and SOCKETS |
| RobMeades | 0:7ccf0e7e8a83 | 419 | **********************************************************************/ |
| RobMeades | 0:7ccf0e7e8a83 | 420 | |
| RobMeades | 0:7ccf0e7e8a83 | 421 | // Gain access to us. |
| RobMeades | 0:7ccf0e7e8a83 | 422 | NetworkStack *UbloxATCellularInterface::get_stack() |
| RobMeades | 0:7ccf0e7e8a83 | 423 | { |
| RobMeades | 0:7ccf0e7e8a83 | 424 | return this; |
| RobMeades | 0:7ccf0e7e8a83 | 425 | } |
| RobMeades | 0:7ccf0e7e8a83 | 426 | |
| RobMeades | 0:7ccf0e7e8a83 | 427 | // Create a socket. |
| RobMeades | 0:7ccf0e7e8a83 | 428 | nsapi_error_t UbloxATCellularInterface::socket_open(nsapi_socket_t *handle, |
| Curt Black |
18:bfc869299185 | 429 | nsapi_protocol_t proto) |
| RobMeades | 0:7ccf0e7e8a83 | 430 | { |
| RobMeades | 0:7ccf0e7e8a83 | 431 | nsapi_error_t nsapi_error = NSAPI_ERROR_DEVICE_ERROR; |
| RobMeades | 0:7ccf0e7e8a83 | 432 | bool success = false; |
| RobMeades | 0:7ccf0e7e8a83 | 433 | int modem_handle; |
| RobMeades | 0:7ccf0e7e8a83 | 434 | SockCtrl *socket; |
| RobMeades | 0:7ccf0e7e8a83 | 435 | LOCK(); |
| RobMeades | 0:7ccf0e7e8a83 | 436 | |
| RobMeades | 0:7ccf0e7e8a83 | 437 | // Find a free socket |
| RobMeades | 0:7ccf0e7e8a83 | 438 | socket = find_socket(); |
| RobMeades | 0:7ccf0e7e8a83 | 439 | tr_debug("socket_open(%d)", proto); |
| RobMeades | 0:7ccf0e7e8a83 | 440 | |
| RobMeades | 0:7ccf0e7e8a83 | 441 | if (socket != NULL) { |
| RobMeades | 0:7ccf0e7e8a83 | 442 | if (proto == NSAPI_UDP) { |
| RobMeades | 0:7ccf0e7e8a83 | 443 | success = _at->send("AT+USOCR=17"); |
| RobMeades | 0:7ccf0e7e8a83 | 444 | } else if (proto == NSAPI_TCP) { |
| RobMeades | 0:7ccf0e7e8a83 | 445 | success = _at->send("AT+USOCR=6"); |
| RobMeades | 0:7ccf0e7e8a83 | 446 | } else { |
| RobMeades | 0:7ccf0e7e8a83 | 447 | nsapi_error = NSAPI_ERROR_UNSUPPORTED; |
| RobMeades | 0:7ccf0e7e8a83 | 448 | } |
| RobMeades | 0:7ccf0e7e8a83 | 449 | |
| RobMeades | 0:7ccf0e7e8a83 | 450 | if (success) { |
| RobMeades | 0:7ccf0e7e8a83 | 451 | nsapi_error = NSAPI_ERROR_NO_SOCKET; |
| RobMeades | 0:7ccf0e7e8a83 | 452 | if (_at->recv("+USOCR: %d\n", &modem_handle) && (modem_handle != SOCKET_UNUSED) && |
| Curt Black |
18:bfc869299185 | 453 | _at->recv("OK")) { |
| RobMeades | 0:7ccf0e7e8a83 | 454 | tr_debug("Socket 0x%8x: handle %d was created", (unsigned int) socket, modem_handle); |
| RobMeades | 0:7ccf0e7e8a83 | 455 | clear_socket(socket); |
| RobMeades | 0:7ccf0e7e8a83 | 456 | socket->modem_handle = modem_handle; |
| RobMeades | 0:7ccf0e7e8a83 | 457 | *handle = (nsapi_socket_t) socket; |
| RobMeades | 0:7ccf0e7e8a83 | 458 | nsapi_error = NSAPI_ERROR_OK; |
| RobMeades | 0:7ccf0e7e8a83 | 459 | } |
| RobMeades | 0:7ccf0e7e8a83 | 460 | } |
| RobMeades | 0:7ccf0e7e8a83 | 461 | } else { |
| RobMeades | 0:7ccf0e7e8a83 | 462 | nsapi_error = NSAPI_ERROR_NO_MEMORY; |
| RobMeades | 0:7ccf0e7e8a83 | 463 | } |
| RobMeades | 0:7ccf0e7e8a83 | 464 | |
| RobMeades | 0:7ccf0e7e8a83 | 465 | UNLOCK(); |
| RobMeades | 0:7ccf0e7e8a83 | 466 | return nsapi_error; |
| RobMeades | 0:7ccf0e7e8a83 | 467 | } |
| RobMeades | 0:7ccf0e7e8a83 | 468 | |
| RobMeades | 0:7ccf0e7e8a83 | 469 | // Close a socket. |
| RobMeades | 0:7ccf0e7e8a83 | 470 | nsapi_error_t UbloxATCellularInterface::socket_close(nsapi_socket_t handle) |
| RobMeades | 0:7ccf0e7e8a83 | 471 | { |
| RobMeades | 0:7ccf0e7e8a83 | 472 | nsapi_error_t nsapi_error = NSAPI_ERROR_DEVICE_ERROR; |
| RobMeades | 0:7ccf0e7e8a83 | 473 | SockCtrl *socket = (SockCtrl *) handle; |
| RobMeades | 0:7ccf0e7e8a83 | 474 | LOCK(); |
| RobMeades | 0:7ccf0e7e8a83 | 475 | |
| RobMeades | 0:7ccf0e7e8a83 | 476 | tr_debug("socket_close(0x%08x)", (unsigned int) handle); |
| RobMeades | 0:7ccf0e7e8a83 | 477 | |
| RobMeades | 0:7ccf0e7e8a83 | 478 | MBED_ASSERT (check_socket(socket)); |
| RobMeades | 0:7ccf0e7e8a83 | 479 | |
| RobMeades | 0:7ccf0e7e8a83 | 480 | if (_at->send("AT+USOCL=%d", socket->modem_handle) && |
| Curt Black |
18:bfc869299185 | 481 | _at->recv("OK")) { |
| RobMeades | 0:7ccf0e7e8a83 | 482 | clear_socket(socket); |
| RobMeades | 0:7ccf0e7e8a83 | 483 | nsapi_error = NSAPI_ERROR_OK; |
| RobMeades | 0:7ccf0e7e8a83 | 484 | } |
| RobMeades | 0:7ccf0e7e8a83 | 485 | |
| RobMeades | 0:7ccf0e7e8a83 | 486 | UNLOCK(); |
| RobMeades | 0:7ccf0e7e8a83 | 487 | return nsapi_error; |
| RobMeades | 0:7ccf0e7e8a83 | 488 | } |
| RobMeades | 0:7ccf0e7e8a83 | 489 | |
| RobMeades | 0:7ccf0e7e8a83 | 490 | // Bind a local port to a socket. |
| RobMeades | 0:7ccf0e7e8a83 | 491 | nsapi_error_t UbloxATCellularInterface::socket_bind(nsapi_socket_t handle, |
| Curt Black |
18:bfc869299185 | 492 | const SocketAddress &address) |
| RobMeades | 0:7ccf0e7e8a83 | 493 | { |
| RobMeades | 0:7ccf0e7e8a83 | 494 | nsapi_error_t nsapi_error = NSAPI_ERROR_NO_SOCKET; |
| RobMeades | 0:7ccf0e7e8a83 | 495 | int proto; |
| RobMeades | 0:7ccf0e7e8a83 | 496 | int modem_handle; |
| RobMeades | 0:7ccf0e7e8a83 | 497 | SockCtrl savedSocket; |
| RobMeades | 0:7ccf0e7e8a83 | 498 | SockCtrl *socket = (SockCtrl *) handle; |
| RobMeades | 0:7ccf0e7e8a83 | 499 | LOCK(); |
| RobMeades | 0:7ccf0e7e8a83 | 500 | |
| RobMeades | 0:7ccf0e7e8a83 | 501 | tr_debug("socket_bind(0x%08x, :%d)", (unsigned int) handle, address.get_port()); |
| RobMeades | 0:7ccf0e7e8a83 | 502 | |
| RobMeades | 0:7ccf0e7e8a83 | 503 | MBED_ASSERT (check_socket(socket)); |
| RobMeades | 0:7ccf0e7e8a83 | 504 | |
| RobMeades | 0:7ccf0e7e8a83 | 505 | // Query the socket type |
| RobMeades | 0:7ccf0e7e8a83 | 506 | if (_at->send("AT+USOCTL=%d,0", socket->modem_handle) && |
| Curt Black |
18:bfc869299185 | 507 | _at->recv("+USOCTL: %*d,0,%d\n", &proto) && |
| Curt Black |
18:bfc869299185 | 508 | _at->recv("OK")) { |
| RobMeades | 0:7ccf0e7e8a83 | 509 | savedSocket = *socket; |
| RobMeades | 0:7ccf0e7e8a83 | 510 | nsapi_error = NSAPI_ERROR_DEVICE_ERROR; |
| RobMeades | 0:7ccf0e7e8a83 | 511 | // Now close the socket and re-open it with the binding given |
| RobMeades | 0:7ccf0e7e8a83 | 512 | if (_at->send("AT+USOCL=%d", socket->modem_handle) && |
| Curt Black |
18:bfc869299185 | 513 | _at->recv("OK")) { |
| RobMeades | 0:7ccf0e7e8a83 | 514 | clear_socket(socket); |
| RobMeades | 0:7ccf0e7e8a83 | 515 | nsapi_error = NSAPI_ERROR_CONNECTION_LOST; |
| RobMeades | 0:7ccf0e7e8a83 | 516 | if (_at->send("AT+USOCR=%d,%d", proto, address.get_port()) && |
| Curt Black |
18:bfc869299185 | 517 | _at->recv("+USOCR: %d\n", &modem_handle) && (modem_handle != SOCKET_UNUSED) && |
| Curt Black |
18:bfc869299185 | 518 | _at->recv("OK")) { |
| RobMeades | 0:7ccf0e7e8a83 | 519 | *socket = savedSocket; |
| RobMeades | 0:7ccf0e7e8a83 | 520 | nsapi_error = NSAPI_ERROR_OK; |
| RobMeades | 0:7ccf0e7e8a83 | 521 | } |
| RobMeades | 0:7ccf0e7e8a83 | 522 | } |
| RobMeades | 0:7ccf0e7e8a83 | 523 | } |
| RobMeades | 0:7ccf0e7e8a83 | 524 | |
| RobMeades | 0:7ccf0e7e8a83 | 525 | UNLOCK(); |
| RobMeades | 0:7ccf0e7e8a83 | 526 | return nsapi_error; |
| RobMeades | 0:7ccf0e7e8a83 | 527 | } |
| RobMeades | 0:7ccf0e7e8a83 | 528 | |
| RobMeades | 0:7ccf0e7e8a83 | 529 | // Connect to a socket |
| RobMeades | 0:7ccf0e7e8a83 | 530 | nsapi_error_t UbloxATCellularInterface::socket_connect(nsapi_socket_t handle, |
| Curt Black |
18:bfc869299185 | 531 | const SocketAddress &address) |
| RobMeades | 0:7ccf0e7e8a83 | 532 | { |
| RobMeades | 0:7ccf0e7e8a83 | 533 | nsapi_error_t nsapi_error = NSAPI_ERROR_DEVICE_ERROR; |
| RobMeades | 0:7ccf0e7e8a83 | 534 | SockCtrl *socket = (SockCtrl *) handle; |
| RobMeades | 0:7ccf0e7e8a83 | 535 | LOCK(); |
| RobMeades | 0:7ccf0e7e8a83 | 536 | |
| RobMeades | 0:7ccf0e7e8a83 | 537 | tr_debug("socket_connect(0x%08x, %s(:%d))", (unsigned int) handle, |
| Curt Black |
18:bfc869299185 | 538 | address.get_ip_address(), address.get_port()); |
| RobMeades | 0:7ccf0e7e8a83 | 539 | |
| RobMeades | 0:7ccf0e7e8a83 | 540 | MBED_ASSERT (check_socket(socket)); |
| RobMeades | 0:7ccf0e7e8a83 | 541 | |
| RobMeades | 0:7ccf0e7e8a83 | 542 | if (_at->send("AT+USOCO=%d,\"%s\",%d", socket->modem_handle, |
| Curt Black |
18:bfc869299185 | 543 | address.get_ip_address(), address.get_port()) && |
| Curt Black |
18:bfc869299185 | 544 | _at->recv("OK")) { |
| RobMeades | 0:7ccf0e7e8a83 | 545 | nsapi_error = NSAPI_ERROR_OK; |
| RobMeades | 0:7ccf0e7e8a83 | 546 | } |
| RobMeades | 0:7ccf0e7e8a83 | 547 | |
| RobMeades | 0:7ccf0e7e8a83 | 548 | UNLOCK(); |
| RobMeades | 0:7ccf0e7e8a83 | 549 | return nsapi_error; |
| RobMeades | 0:7ccf0e7e8a83 | 550 | } |
| RobMeades | 0:7ccf0e7e8a83 | 551 | |
| RobMeades | 0:7ccf0e7e8a83 | 552 | // Send to a socket. |
| RobMeades | 0:7ccf0e7e8a83 | 553 | nsapi_size_or_error_t UbloxATCellularInterface::socket_send(nsapi_socket_t handle, |
| Curt Black |
18:bfc869299185 | 554 | const void *data, |
| Curt Black |
18:bfc869299185 | 555 | nsapi_size_t size) |
| RobMeades | 0:7ccf0e7e8a83 | 556 | { |
| RobMeades | 0:7ccf0e7e8a83 | 557 | nsapi_size_or_error_t nsapi_error_size = NSAPI_ERROR_DEVICE_ERROR; |
| RobMeades | 0:7ccf0e7e8a83 | 558 | bool success = true; |
| RobMeades | 0:7ccf0e7e8a83 | 559 | const char *buf = (const char *) data; |
| RobMeades | 0:7ccf0e7e8a83 | 560 | nsapi_size_t blk = MAX_WRITE_SIZE; |
| RobMeades | 0:7ccf0e7e8a83 | 561 | nsapi_size_t count = size; |
| RobMeades | 0:7ccf0e7e8a83 | 562 | SockCtrl *socket = (SockCtrl *) handle; |
| RobMeades | 0:7ccf0e7e8a83 | 563 | |
| RobMeades | 0:7ccf0e7e8a83 | 564 | tr_debug("socket_send(0x%08x, 0x%08x, %d)", (unsigned int) handle, (unsigned int) data, size); |
| RobMeades | 0:7ccf0e7e8a83 | 565 | |
| RobMeades | 0:7ccf0e7e8a83 | 566 | MBED_ASSERT (check_socket(socket)); |
| RobMeades | 0:7ccf0e7e8a83 | 567 | |
| RobMeades | 15:8cc9a80ac0ad | 568 | if (socket->modem_handle == SOCKET_UNUSED) { |
| RobMeades | 15:8cc9a80ac0ad | 569 | tr_debug("socket_send: socket closed"); |
| RobMeades | 15:8cc9a80ac0ad | 570 | return NSAPI_ERROR_NO_SOCKET; |
| RobMeades | 15:8cc9a80ac0ad | 571 | } |
| RobMeades | 15:8cc9a80ac0ad | 572 | |
| RobMeades | 0:7ccf0e7e8a83 | 573 | while ((count > 0) && success) { |
| RobMeades | 0:7ccf0e7e8a83 | 574 | if (count < blk) { |
| RobMeades | 0:7ccf0e7e8a83 | 575 | blk = count; |
| RobMeades | 0:7ccf0e7e8a83 | 576 | } |
| RobMeades | 0:7ccf0e7e8a83 | 577 | LOCK(); |
| RobMeades | 0:7ccf0e7e8a83 | 578 | |
| RobMeades | 0:7ccf0e7e8a83 | 579 | if (_at->send("AT+USOWR=%d,%d", socket->modem_handle, blk) && _at->recv("@")) { |
| RobMeades | 0:7ccf0e7e8a83 | 580 | wait_ms(50); |
| RobMeades | 0:7ccf0e7e8a83 | 581 | if ((_at->write(buf, blk) < (int) blk) || |
| Curt Black |
18:bfc869299185 | 582 | !_at->recv("OK")) { |
| RobMeades | 0:7ccf0e7e8a83 | 583 | success = false; |
| RobMeades | 0:7ccf0e7e8a83 | 584 | } |
| RobMeades | 0:7ccf0e7e8a83 | 585 | } else { |
| RobMeades | 0:7ccf0e7e8a83 | 586 | success = false; |
| RobMeades | 0:7ccf0e7e8a83 | 587 | } |
| RobMeades | 0:7ccf0e7e8a83 | 588 | |
| RobMeades | 0:7ccf0e7e8a83 | 589 | UNLOCK(); |
| RobMeades | 0:7ccf0e7e8a83 | 590 | buf += blk; |
| RobMeades | 0:7ccf0e7e8a83 | 591 | count -= blk; |
| RobMeades | 0:7ccf0e7e8a83 | 592 | } |
| RobMeades | 0:7ccf0e7e8a83 | 593 | |
| RobMeades | 0:7ccf0e7e8a83 | 594 | if (success) { |
| RobMeades | 0:7ccf0e7e8a83 | 595 | nsapi_error_size = size - count; |
| RobMeades | 0:7ccf0e7e8a83 | 596 | if (_debug_trace_on) { |
| RobMeades | 0:7ccf0e7e8a83 | 597 | tr_debug("socket_send: %d \"%*.*s\"", size, size, size, (char *) data); |
| RobMeades | 0:7ccf0e7e8a83 | 598 | } |
| RobMeades | 0:7ccf0e7e8a83 | 599 | } |
| RobMeades | 0:7ccf0e7e8a83 | 600 | |
| RobMeades | 0:7ccf0e7e8a83 | 601 | return nsapi_error_size; |
| RobMeades | 0:7ccf0e7e8a83 | 602 | } |
| RobMeades | 0:7ccf0e7e8a83 | 603 | |
| RobMeades | 0:7ccf0e7e8a83 | 604 | // Send to an IP address. |
| RobMeades | 0:7ccf0e7e8a83 | 605 | nsapi_size_or_error_t UbloxATCellularInterface::socket_sendto(nsapi_socket_t handle, |
| Curt Black |
18:bfc869299185 | 606 | const SocketAddress &address, |
| Curt Black |
18:bfc869299185 | 607 | const void *data, |
| Curt Black |
18:bfc869299185 | 608 | nsapi_size_t size) |
| RobMeades | 0:7ccf0e7e8a83 | 609 | { |
| RobMeades | 0:7ccf0e7e8a83 | 610 | nsapi_size_or_error_t nsapi_error_size = NSAPI_ERROR_DEVICE_ERROR; |
| RobMeades | 0:7ccf0e7e8a83 | 611 | bool success = true; |
| RobMeades | 0:7ccf0e7e8a83 | 612 | const char *buf = (const char *) data; |
| RobMeades | 0:7ccf0e7e8a83 | 613 | nsapi_size_t blk = MAX_WRITE_SIZE; |
| RobMeades | 0:7ccf0e7e8a83 | 614 | nsapi_size_t count = size; |
| RobMeades | 0:7ccf0e7e8a83 | 615 | SockCtrl *socket = (SockCtrl *) handle; |
| RobMeades | 0:7ccf0e7e8a83 | 616 | |
| RobMeades | 0:7ccf0e7e8a83 | 617 | tr_debug("socket_sendto(0x%8x, %s(:%d), 0x%08x, %d)", (unsigned int) handle, |
| Curt Black |
18:bfc869299185 | 618 | address.get_ip_address(), address.get_port(), (unsigned int) data, size); |
| RobMeades | 0:7ccf0e7e8a83 | 619 | |
| RobMeades | 0:7ccf0e7e8a83 | 620 | MBED_ASSERT (check_socket(socket)); |
| RobMeades | 0:7ccf0e7e8a83 | 621 | |
| RobMeades | 0:7ccf0e7e8a83 | 622 | if (size > MAX_WRITE_SIZE) { |
| RobMeades | 0:7ccf0e7e8a83 | 623 | tr_warn("WARNING: packet length %d is too big for one UDP packet (max %d), will be fragmented.", size, MAX_WRITE_SIZE); |
| RobMeades | 0:7ccf0e7e8a83 | 624 | } |
| RobMeades | 0:7ccf0e7e8a83 | 625 | |
| RobMeades | 0:7ccf0e7e8a83 | 626 | while ((count > 0) && success) { |
| RobMeades | 0:7ccf0e7e8a83 | 627 | if (count < blk) { |
| RobMeades | 0:7ccf0e7e8a83 | 628 | blk = count; |
| RobMeades | 0:7ccf0e7e8a83 | 629 | } |
| RobMeades | 0:7ccf0e7e8a83 | 630 | LOCK(); |
| RobMeades | 0:7ccf0e7e8a83 | 631 | |
| RobMeades | 0:7ccf0e7e8a83 | 632 | if (_at->send("AT+USOST=%d,\"%s\",%d,%d", socket->modem_handle, |
| Curt Black |
18:bfc869299185 | 633 | address.get_ip_address(), address.get_port(), blk) && |
| Curt Black |
18:bfc869299185 | 634 | _at->recv("@")) { |
| RobMeades | 0:7ccf0e7e8a83 | 635 | wait_ms(50); |
| RobMeades | 0:7ccf0e7e8a83 | 636 | if ((_at->write(buf, blk) >= (int) blk) && |
| Curt Black |
18:bfc869299185 | 637 | _at->recv("OK")) { |
| RobMeades | 0:7ccf0e7e8a83 | 638 | } else { |
| RobMeades | 0:7ccf0e7e8a83 | 639 | success = false; |
| RobMeades | 0:7ccf0e7e8a83 | 640 | } |
| RobMeades | 0:7ccf0e7e8a83 | 641 | } else { |
| RobMeades | 0:7ccf0e7e8a83 | 642 | success = false; |
| RobMeades | 0:7ccf0e7e8a83 | 643 | } |
| RobMeades | 0:7ccf0e7e8a83 | 644 | |
| RobMeades | 0:7ccf0e7e8a83 | 645 | UNLOCK(); |
| RobMeades | 0:7ccf0e7e8a83 | 646 | buf += blk; |
| RobMeades | 0:7ccf0e7e8a83 | 647 | count -= blk; |
| RobMeades | 0:7ccf0e7e8a83 | 648 | } |
| RobMeades | 0:7ccf0e7e8a83 | 649 | |
| RobMeades | 0:7ccf0e7e8a83 | 650 | if (success) { |
| RobMeades | 0:7ccf0e7e8a83 | 651 | nsapi_error_size = size - count; |
| RobMeades | 0:7ccf0e7e8a83 | 652 | if (_debug_trace_on) { |
| RobMeades | 0:7ccf0e7e8a83 | 653 | tr_debug("socket_sendto: %d \"%*.*s\"", size, size, size, (char *) data); |
| RobMeades | 0:7ccf0e7e8a83 | 654 | } |
| RobMeades | 0:7ccf0e7e8a83 | 655 | } |
| RobMeades | 0:7ccf0e7e8a83 | 656 | |
| RobMeades | 0:7ccf0e7e8a83 | 657 | return nsapi_error_size; |
| RobMeades | 0:7ccf0e7e8a83 | 658 | } |
| RobMeades | 0:7ccf0e7e8a83 | 659 | |
| RobMeades | 0:7ccf0e7e8a83 | 660 | // Receive from a socket, TCP style. |
| RobMeades | 0:7ccf0e7e8a83 | 661 | nsapi_size_or_error_t UbloxATCellularInterface::socket_recv(nsapi_socket_t handle, |
| Curt Black |
18:bfc869299185 | 662 | void *data, |
| Curt Black |
18:bfc869299185 | 663 | nsapi_size_t size) |
| RobMeades | 0:7ccf0e7e8a83 | 664 | { |
| RobMeades | 0:7ccf0e7e8a83 | 665 | nsapi_size_or_error_t nsapi_error_size = NSAPI_ERROR_DEVICE_ERROR; |
| RobMeades | 0:7ccf0e7e8a83 | 666 | bool success = true; |
| RobMeades | 0:7ccf0e7e8a83 | 667 | char *buf = (char *) data; |
| RobMeades | 0:7ccf0e7e8a83 | 668 | nsapi_size_t read_blk; |
| RobMeades | 0:7ccf0e7e8a83 | 669 | nsapi_size_t count = 0; |
| RobMeades | 0:7ccf0e7e8a83 | 670 | unsigned int usord_sz; |
| RobMeades | 0:7ccf0e7e8a83 | 671 | int read_sz; |
| RobMeades | 0:7ccf0e7e8a83 | 672 | Timer timer; |
| RobMeades | 0:7ccf0e7e8a83 | 673 | SockCtrl *socket = (SockCtrl *) handle; |
| RobMeades | 0:7ccf0e7e8a83 | 674 | int at_timeout; |
| RobMeades | 0:7ccf0e7e8a83 | 675 | |
| RobMeades | 0:7ccf0e7e8a83 | 676 | tr_debug("socket_recv(0x%08x, 0x%08x, %d)", |
| Curt Black |
18:bfc869299185 | 677 | (unsigned int) handle, (unsigned int) data, size); |
| RobMeades | 0:7ccf0e7e8a83 | 678 | |
| RobMeades | 0:7ccf0e7e8a83 | 679 | MBED_ASSERT (check_socket(socket)); |
| RobMeades | 0:7ccf0e7e8a83 | 680 | |
| RobMeades | 15:8cc9a80ac0ad | 681 | if (socket->modem_handle == SOCKET_UNUSED) { |
| RobMeades | 15:8cc9a80ac0ad | 682 | tr_debug("socket_recv: socket closed"); |
| RobMeades | 15:8cc9a80ac0ad | 683 | return NSAPI_ERROR_NO_SOCKET; |
| RobMeades | 15:8cc9a80ac0ad | 684 | } |
| RobMeades | 15:8cc9a80ac0ad | 685 | |
| RobMeades | 0:7ccf0e7e8a83 | 686 | timer.start(); |
| RobMeades | 0:7ccf0e7e8a83 | 687 | |
| RobMeades | 0:7ccf0e7e8a83 | 688 | while (success && (size > 0)) { |
| RobMeades | 0:7ccf0e7e8a83 | 689 | LOCK(); |
| RobMeades | 0:7ccf0e7e8a83 | 690 | at_timeout = _at_timeout; |
| RobMeades | 0:7ccf0e7e8a83 | 691 | at_set_timeout(1000); |
| RobMeades | 0:7ccf0e7e8a83 | 692 | |
| Curt Black |
18:bfc869299185 | 693 | do { |
| Curt Black |
18:bfc869299185 | 694 | |
| Curt Black |
18:bfc869299185 | 695 | #ifdef USE_HEX_MODE_USORx |
| Curt Black |
18:bfc869299185 | 696 | if (_at->send("AT+UDCONF=1,1") && _at->recv("OK")) { |
| Curt Black |
18:bfc869299185 | 697 | } else { |
| Curt Black |
18:bfc869299185 | 698 | success = false; |
| Curt Black |
18:bfc869299185 | 699 | break; |
| Curt Black |
18:bfc869299185 | 700 | } |
| Curt Black |
18:bfc869299185 | 701 | #endif |
| Curt Black |
18:bfc869299185 | 702 | read_blk = MAX_READ_SIZE; |
| Curt Black |
18:bfc869299185 | 703 | if (read_blk > size) { |
| Curt Black |
18:bfc869299185 | 704 | read_blk = size; |
| Curt Black |
18:bfc869299185 | 705 | } |
| Curt Black |
18:bfc869299185 | 706 | if (socket->pending > 0) { |
| Curt Black |
18:bfc869299185 | 707 | tr_debug("Socket 0x%08x: modem handle %d has %d byte(s) pending", |
| Curt Black |
18:bfc869299185 | 708 | (unsigned int) socket, socket->modem_handle, socket->pending); |
| Curt Black |
18:bfc869299185 | 709 | _at->debug_on(false); // ABSOLUTELY no time for debug here if you want to |
| Curt Black |
18:bfc869299185 | 710 | // be able to read packets of any size without |
| Curt Black |
18:bfc869299185 | 711 | // losing characters in UARTSerial |
| Curt Black |
18:bfc869299185 | 712 | if (_at->send("AT+USORD=%d,%d", socket->modem_handle, read_blk) && |
| Curt Black |
18:bfc869299185 | 713 | _at->recv("+USORD: %*d,%d,\"", &usord_sz)) { |
| Curt Black |
18:bfc869299185 | 714 | // Must use what +USORD returns here as it may be less or more than we asked for |
| Curt Black |
18:bfc869299185 | 715 | if (usord_sz > socket->pending) { |
| Curt Black |
18:bfc869299185 | 716 | socket->pending = 0; |
| Curt Black |
18:bfc869299185 | 717 | } else { |
| Curt Black |
18:bfc869299185 | 718 | socket->pending -= usord_sz; |
| Curt Black |
18:bfc869299185 | 719 | } |
| Curt Black |
18:bfc869299185 | 720 | // Note: insert no debug between _at->recv() and _at->read(), no time... |
| Curt Black |
18:bfc869299185 | 721 | if (usord_sz > size) { |
| Curt Black |
18:bfc869299185 | 722 | usord_sz = size; |
| Curt Black |
18:bfc869299185 | 723 | } |
| Curt Black |
18:bfc869299185 | 724 | #ifdef USE_HEX_MODE_USORx |
| Curt Black |
18:bfc869299185 | 725 | read_sz = 0; |
| Curt Black |
18:bfc869299185 | 726 | char asciiBytes[2]; |
| cblack | 19:2e961ce171e6 | 727 | while (success && (read_sz < usord_sz*2)) { |
| Curt Black |
18:bfc869299185 | 728 | // Read the 2 bytes of ascii text for this byte of data |
| Curt Black |
18:bfc869299185 | 729 | if (2 == _at->read(asciiBytes, 2)) { |
| Curt Black |
18:bfc869299185 | 730 | read_sz += 2; |
| Curt Black |
18:bfc869299185 | 731 | // convert to binary data and store in read buffer |
| Curt Black |
18:bfc869299185 | 732 | sscanf(asciiBytes, "%2hhx", buf+(read_sz/2)); |
| Curt Black |
18:bfc869299185 | 733 | } else { |
| Curt Black |
18:bfc869299185 | 734 | success = false; |
| Curt Black |
18:bfc869299185 | 735 | } |
| Curt Black |
18:bfc869299185 | 736 | } |
| Curt Black |
18:bfc869299185 | 737 | #else |
| Curt Black |
18:bfc869299185 | 738 | read_sz = _at->read(buf, usorf_sz); |
| Curt Black |
18:bfc869299185 | 739 | #endif |
| Curt Black |
18:bfc869299185 | 740 | if (read_sz > 0) { |
| Curt Black |
18:bfc869299185 | 741 | tr_debug("...read %d byte(s) from modem handle %d...", read_sz, |
| Curt Black |
18:bfc869299185 | 742 | socket->modem_handle); |
| Curt Black |
18:bfc869299185 | 743 | if (_debug_trace_on) { |
| Curt Black |
18:bfc869299185 | 744 | tr_debug("Read returned %d, |%*.*s|", read_sz, read_sz, read_sz, buf); |
| Curt Black |
18:bfc869299185 | 745 | } |
| Curt Black |
18:bfc869299185 | 746 | count += read_sz; |
| Curt Black |
18:bfc869299185 | 747 | buf += read_sz; |
| Curt Black |
18:bfc869299185 | 748 | size -= read_sz; |
| Curt Black |
18:bfc869299185 | 749 | } else { |
| Curt Black |
18:bfc869299185 | 750 | // read() should not fail |
| Curt Black |
18:bfc869299185 | 751 | success = false; |
| Curt Black |
18:bfc869299185 | 752 | } |
| Curt Black |
18:bfc869299185 | 753 | tr_debug("Socket 0x%08x: modem handle %d now has only %d byte(s) pending", |
| Curt Black |
18:bfc869299185 | 754 | (unsigned int) socket, socket->modem_handle, socket->pending); |
| Curt Black |
18:bfc869299185 | 755 | // Wait for the "OK" before continuing |
| Curt Black |
18:bfc869299185 | 756 | _at->recv("OK"); |
| RobMeades | 10:ba18f4418ee8 | 757 | } else { |
| Curt Black |
18:bfc869299185 | 758 | // Should never fail to do _at->send()/_at->recv() |
| RobMeades | 0:7ccf0e7e8a83 | 759 | success = false; |
| RobMeades | 0:7ccf0e7e8a83 | 760 | } |
| Curt Black |
18:bfc869299185 | 761 | _at->debug_on(_debug_trace_on); |
| Curt Black |
18:bfc869299185 | 762 | } else if (timer.read_ms() < SOCKET_TIMEOUT) { |
| Curt Black |
18:bfc869299185 | 763 | // Wait for URCs |
| Curt Black |
18:bfc869299185 | 764 | _at->recv(UNNATURAL_STRING); |
| RobMeades | 0:7ccf0e7e8a83 | 765 | } else { |
| Curt Black |
18:bfc869299185 | 766 | if (count == 0) { |
| Curt Black |
18:bfc869299185 | 767 | // Timeout with nothing received |
| Curt Black |
18:bfc869299185 | 768 | nsapi_error_size = NSAPI_ERROR_WOULD_BLOCK; |
| Curt Black |
18:bfc869299185 | 769 | success = false; |
| Curt Black |
18:bfc869299185 | 770 | } |
| Curt Black |
18:bfc869299185 | 771 | size = 0; // This simply to cause an exit |
| RobMeades | 0:7ccf0e7e8a83 | 772 | } |
| Curt Black |
18:bfc869299185 | 773 | |
| Curt Black |
18:bfc869299185 | 774 | } while (0); // Any fails that set success=false can simply break, avoids even worse nested if's |
| Curt Black |
18:bfc869299185 | 775 | |
| Curt Black |
18:bfc869299185 | 776 | #ifdef USE_HEX_MODE_USORx |
| Curt Black |
18:bfc869299185 | 777 | // Set back to non-hex mode |
| Curt Black |
18:bfc869299185 | 778 | if (_at->send("AT+UDCONF=1,0") && _at->recv("OK")) { |
| RobMeades | 0:7ccf0e7e8a83 | 779 | } else { |
| Curt Black |
18:bfc869299185 | 780 | success = false; |
| Curt Black |
18:bfc869299185 | 781 | break; |
| RobMeades | 0:7ccf0e7e8a83 | 782 | } |
| Curt Black |
18:bfc869299185 | 783 | #endif |
| RobMeades | 0:7ccf0e7e8a83 | 784 | |
| RobMeades | 0:7ccf0e7e8a83 | 785 | at_set_timeout(at_timeout); |
| RobMeades | 0:7ccf0e7e8a83 | 786 | UNLOCK(); |
| RobMeades | 0:7ccf0e7e8a83 | 787 | } |
| RobMeades | 0:7ccf0e7e8a83 | 788 | timer.stop(); |
| RobMeades | 0:7ccf0e7e8a83 | 789 | |
| RobMeades | 0:7ccf0e7e8a83 | 790 | if (success) { |
| RobMeades | 0:7ccf0e7e8a83 | 791 | nsapi_error_size = count; |
| RobMeades | 0:7ccf0e7e8a83 | 792 | } |
| RobMeades | 0:7ccf0e7e8a83 | 793 | |
| RobMeades | 0:7ccf0e7e8a83 | 794 | if (_debug_trace_on) { |
| RobMeades | 0:7ccf0e7e8a83 | 795 | tr_debug("socket_recv: %d \"%*.*s\"", count, count, count, buf - count); |
| RobMeades | 0:7ccf0e7e8a83 | 796 | } else { |
| RobMeades | 0:7ccf0e7e8a83 | 797 | tr_debug("socket_recv: received %d byte(s)", count); |
| RobMeades | 0:7ccf0e7e8a83 | 798 | } |
| RobMeades | 0:7ccf0e7e8a83 | 799 | |
| RobMeades | 0:7ccf0e7e8a83 | 800 | return nsapi_error_size; |
| RobMeades | 0:7ccf0e7e8a83 | 801 | } |
| RobMeades | 0:7ccf0e7e8a83 | 802 | |
| RobMeades | 0:7ccf0e7e8a83 | 803 | // Receive a packet over a UDP socket. |
| RobMeades | 0:7ccf0e7e8a83 | 804 | nsapi_size_or_error_t UbloxATCellularInterface::socket_recvfrom(nsapi_socket_t handle, |
| Curt Black |
18:bfc869299185 | 805 | SocketAddress *address, |
| Curt Black |
18:bfc869299185 | 806 | void *data, |
| Curt Black |
18:bfc869299185 | 807 | nsapi_size_t size) |
| RobMeades | 0:7ccf0e7e8a83 | 808 | { |
| RobMeades | 0:7ccf0e7e8a83 | 809 | nsapi_size_or_error_t nsapi_error_size = NSAPI_ERROR_DEVICE_ERROR; |
| RobMeades | 0:7ccf0e7e8a83 | 810 | bool success = true; |
| RobMeades | 0:7ccf0e7e8a83 | 811 | char *buf = (char *) data; |
| RobMeades | 0:7ccf0e7e8a83 | 812 | nsapi_size_t read_blk; |
| RobMeades | 0:7ccf0e7e8a83 | 813 | nsapi_size_t count = 0; |
| RobMeades | 0:7ccf0e7e8a83 | 814 | char ipAddress[NSAPI_IP_SIZE]; |
| RobMeades | 0:7ccf0e7e8a83 | 815 | int port; |
| RobMeades | 0:7ccf0e7e8a83 | 816 | unsigned int usorf_sz; |
| RobMeades | 0:7ccf0e7e8a83 | 817 | int read_sz; |
| RobMeades | 0:7ccf0e7e8a83 | 818 | Timer timer; |
| RobMeades | 0:7ccf0e7e8a83 | 819 | SockCtrl *socket = (SockCtrl *) handle; |
| RobMeades | 0:7ccf0e7e8a83 | 820 | int at_timeout; |
| RobMeades | 0:7ccf0e7e8a83 | 821 | |
| RobMeades | 0:7ccf0e7e8a83 | 822 | tr_debug("socket_recvfrom(0x%08x, 0x%08x, %d)", |
| Curt Black |
18:bfc869299185 | 823 | (unsigned int) handle, (unsigned int) data, size); |
| RobMeades | 0:7ccf0e7e8a83 | 824 | |
| RobMeades | 0:7ccf0e7e8a83 | 825 | MBED_ASSERT (check_socket(socket)); |
| RobMeades | 0:7ccf0e7e8a83 | 826 | |
| RobMeades | 0:7ccf0e7e8a83 | 827 | timer.start(); |
| RobMeades | 0:7ccf0e7e8a83 | 828 | |
| RobMeades | 0:7ccf0e7e8a83 | 829 | while (success && (size > 0)) { |
| RobMeades | 0:7ccf0e7e8a83 | 830 | LOCK(); |
| RobMeades | 0:7ccf0e7e8a83 | 831 | at_timeout = _at_timeout; |
| RobMeades | 0:7ccf0e7e8a83 | 832 | at_set_timeout(1000); |
| RobMeades | 0:7ccf0e7e8a83 | 833 | |
| Curt Black |
18:bfc869299185 | 834 | do { |
| RobMeades | 0:7ccf0e7e8a83 | 835 | |
| Curt Black |
18:bfc869299185 | 836 | #ifdef USE_HEX_MODE_USORx |
| Curt Black |
18:bfc869299185 | 837 | if (_at->send("AT+UDCONF=1,1") && _at->recv("OK")) { |
| Curt Black |
18:bfc869299185 | 838 | } else { |
| Curt Black |
18:bfc869299185 | 839 | success = false; |
| Curt Black |
18:bfc869299185 | 840 | break; |
| Curt Black |
18:bfc869299185 | 841 | } |
| Curt Black |
18:bfc869299185 | 842 | #endif |
| Curt Black |
18:bfc869299185 | 843 | read_blk = MAX_READ_SIZE; |
| Curt Black |
18:bfc869299185 | 844 | if (read_blk > size) { |
| Curt Black |
18:bfc869299185 | 845 | read_blk = size; |
| Curt Black |
18:bfc869299185 | 846 | } |
| Curt Black |
18:bfc869299185 | 847 | if (socket->pending > 0) { |
| Curt Black |
18:bfc869299185 | 848 | tr_debug("Socket 0x%08x: modem handle %d has %d byte(s) pending", |
| Curt Black |
18:bfc869299185 | 849 | (unsigned int) socket, socket->modem_handle, socket->pending); |
| Curt Black |
18:bfc869299185 | 850 | memset (ipAddress, 0, sizeof (ipAddress)); // Ensure terminator |
| Curt Black |
18:bfc869299185 | 851 | |
| Curt Black |
18:bfc869299185 | 852 | // Note: the maximum length of UDP packet we can receive comes from |
| Curt Black |
18:bfc869299185 | 853 | // fitting all of the following into one buffer: |
| Curt Black |
18:bfc869299185 | 854 | // |
| Curt Black |
18:bfc869299185 | 855 | // +USORF: xx,"max.len.ip.address.ipv4.or.ipv6",yyyyy,wwww,"the_data"\r\n |
| Curt Black |
18:bfc869299185 | 856 | // |
| Curt Black |
18:bfc869299185 | 857 | // where xx is the handle, max.len.ip.address.ipv4.or.ipv6 is NSAPI_IP_SIZE, |
| Curt Black |
18:bfc869299185 | 858 | // yyyyy is the port number (max 65536), wwww is the length of the data and |
| Curt Black |
18:bfc869299185 | 859 | // the_data is binary data. I make that 29 + 48 + len(the_data), |
| Curt Black |
18:bfc869299185 | 860 | // so the overhead is 77 bytes. |
| RobMeades | 0:7ccf0e7e8a83 | 861 | |
| cblack | 19:2e961ce171e6 | 862 | //_at->debug_on(false); // ABSOLUTELY no time for debug here if you want to |
| Curt Black |
18:bfc869299185 | 863 | // be able to read packets of any size without |
| Curt Black |
18:bfc869299185 | 864 | // losing characters in UARTSerial |
| Curt Black |
18:bfc869299185 | 865 | if (_at->send("AT+USORF=%d,%d", socket->modem_handle, read_blk) && |
| Curt Black |
18:bfc869299185 | 866 | _at->recv("+USORF: %*d,\"%" u_stringify(NSAPI_IP_SIZE) "[^\"]\",%d,%d,\"", |
| Curt Black |
18:bfc869299185 | 867 | ipAddress, &port, &usorf_sz)) { |
| Curt Black |
18:bfc869299185 | 868 | // Must use what +USORF returns here as it may be less or more than we asked for |
| Curt Black |
18:bfc869299185 | 869 | if (usorf_sz > socket->pending) { |
| Curt Black |
18:bfc869299185 | 870 | socket->pending = 0; |
| Curt Black |
18:bfc869299185 | 871 | } else { |
| Curt Black |
18:bfc869299185 | 872 | socket->pending -= usorf_sz; |
| Curt Black |
18:bfc869299185 | 873 | } |
| Curt Black |
18:bfc869299185 | 874 | // Note: insert no debug between _at->recv() and _at->read(), no time... |
| Curt Black |
18:bfc869299185 | 875 | if (usorf_sz > size) { |
| Curt Black |
18:bfc869299185 | 876 | usorf_sz = size; |
| Curt Black |
18:bfc869299185 | 877 | } |
| Curt Black |
18:bfc869299185 | 878 | #ifdef USE_HEX_MODE_USORx |
| Curt Black |
18:bfc869299185 | 879 | read_sz = 0; |
| Curt Black |
18:bfc869299185 | 880 | char asciiBytes[2]; |
| cblack | 19:2e961ce171e6 | 881 | while (success && (read_sz < usorf_sz*2)) { |
| Curt Black |
18:bfc869299185 | 882 | // Read the 2 bytes of ascii text for this byte of data |
| Curt Black |
18:bfc869299185 | 883 | if (2 == _at->read(asciiBytes, 2)) { |
| Curt Black |
18:bfc869299185 | 884 | // convert to binary data and store in read buffer |
| Curt Black |
18:bfc869299185 | 885 | sscanf(asciiBytes, "%2hhx", buf+(read_sz/2)); |
| Curt Black |
18:bfc869299185 | 886 | read_sz += 2; |
| Curt Black |
18:bfc869299185 | 887 | } else { |
| Curt Black |
18:bfc869299185 | 888 | success = false; |
| Curt Black |
18:bfc869299185 | 889 | } |
| Curt Black |
18:bfc869299185 | 890 | } |
| Curt Black |
18:bfc869299185 | 891 | #else |
| Curt Black |
18:bfc869299185 | 892 | read_sz = _at->read(buf, usorf_sz); |
| Curt Black |
18:bfc869299185 | 893 | #endif |
| Curt Black |
18:bfc869299185 | 894 | if (read_sz > 0) { |
| Curt Black |
18:bfc869299185 | 895 | address->set_ip_address(ipAddress); |
| Curt Black |
18:bfc869299185 | 896 | address->set_port(port); |
| Curt Black |
18:bfc869299185 | 897 | tr_debug("...read %d byte(s) from modem handle %d...", read_sz, |
| Curt Black |
18:bfc869299185 | 898 | socket->modem_handle); |
| Curt Black |
18:bfc869299185 | 899 | if (_debug_trace_on) { |
| Curt Black |
18:bfc869299185 | 900 | tr_debug("Read returned %d, |%*.*s|", read_sz, read_sz, read_sz, buf); |
| Curt Black |
18:bfc869299185 | 901 | } |
| Curt Black |
18:bfc869299185 | 902 | count += read_sz; |
| Curt Black |
18:bfc869299185 | 903 | buf += read_sz; |
| Curt Black |
18:bfc869299185 | 904 | size -= read_sz; |
| Curt Black |
18:bfc869299185 | 905 | if ((usorf_sz < read_blk) || (usorf_sz == MAX_READ_SIZE)) { |
| Curt Black |
18:bfc869299185 | 906 | size = 0; // If we've received less than we asked for, or |
| Curt Black |
18:bfc869299185 | 907 | // the max size, then a whole UDP packet has arrived and |
| Curt Black |
18:bfc869299185 | 908 | // this means DONE. |
| Curt Black |
18:bfc869299185 | 909 | } |
| Curt Black |
18:bfc869299185 | 910 | } else { |
| Curt Black |
18:bfc869299185 | 911 | // read() should not fail |
| Curt Black |
18:bfc869299185 | 912 | success = false; |
| Curt Black |
18:bfc869299185 | 913 | } |
| Curt Black |
18:bfc869299185 | 914 | tr_debug("Socket 0x%08x: modem handle %d now has only %d byte(s) pending", |
| Curt Black |
18:bfc869299185 | 915 | (unsigned int) socket, socket->modem_handle, socket->pending); |
| Curt Black |
18:bfc869299185 | 916 | // Wait for the "OK" before continuing |
| Curt Black |
18:bfc869299185 | 917 | _at->recv("OK"); |
| RobMeades | 10:ba18f4418ee8 | 918 | } else { |
| Curt Black |
18:bfc869299185 | 919 | // Should never fail to do _at->send()/_at->recv() |
| RobMeades | 0:7ccf0e7e8a83 | 920 | success = false; |
| RobMeades | 0:7ccf0e7e8a83 | 921 | } |
| Curt Black |
18:bfc869299185 | 922 | _at->debug_on(_debug_trace_on); |
| Curt Black |
18:bfc869299185 | 923 | } else if (timer.read_ms() < SOCKET_TIMEOUT) { |
| Curt Black |
18:bfc869299185 | 924 | // Wait for URCs |
| Curt Black |
18:bfc869299185 | 925 | _at->recv(UNNATURAL_STRING); |
| RobMeades | 0:7ccf0e7e8a83 | 926 | } else { |
| Curt Black |
18:bfc869299185 | 927 | if (count == 0) { |
| Curt Black |
18:bfc869299185 | 928 | // Timeout with nothing received |
| Curt Black |
18:bfc869299185 | 929 | nsapi_error_size = NSAPI_ERROR_WOULD_BLOCK; |
| Curt Black |
18:bfc869299185 | 930 | success = false; |
| Curt Black |
18:bfc869299185 | 931 | } |
| Curt Black |
18:bfc869299185 | 932 | size = 0; // This simply to cause an exit |
| RobMeades | 0:7ccf0e7e8a83 | 933 | } |
| Curt Black |
18:bfc869299185 | 934 | |
| Curt Black |
18:bfc869299185 | 935 | } while (0); // Any fails that set success=false can simply break, avoids even worse nested if's |
| Curt Black |
18:bfc869299185 | 936 | |
| Curt Black |
18:bfc869299185 | 937 | #ifdef USE_HEX_MODE_USORx |
| Curt Black |
18:bfc869299185 | 938 | // Set back to non-hex mode |
| Curt Black |
18:bfc869299185 | 939 | if (_at->send("AT+UDCONF=1,0") && _at->recv("OK")) { |
| RobMeades | 0:7ccf0e7e8a83 | 940 | } else { |
| Curt Black |
18:bfc869299185 | 941 | success = false; |
| Curt Black |
18:bfc869299185 | 942 | break; |
| RobMeades | 0:7ccf0e7e8a83 | 943 | } |
| Curt Black |
18:bfc869299185 | 944 | #endif |
| RobMeades | 0:7ccf0e7e8a83 | 945 | at_set_timeout(at_timeout); |
| RobMeades | 0:7ccf0e7e8a83 | 946 | UNLOCK(); |
| RobMeades | 0:7ccf0e7e8a83 | 947 | } |
| RobMeades | 0:7ccf0e7e8a83 | 948 | timer.stop(); |
| RobMeades | 0:7ccf0e7e8a83 | 949 | |
| RobMeades | 0:7ccf0e7e8a83 | 950 | if (success) { |
| RobMeades | 0:7ccf0e7e8a83 | 951 | nsapi_error_size = count; |
| RobMeades | 0:7ccf0e7e8a83 | 952 | } |
| RobMeades | 0:7ccf0e7e8a83 | 953 | |
| RobMeades | 0:7ccf0e7e8a83 | 954 | if (_debug_trace_on) { |
| RobMeades | 0:7ccf0e7e8a83 | 955 | tr_debug("socket_recvfrom: %d \"%*.*s\"", count, count, count, buf - count); |
| RobMeades | 0:7ccf0e7e8a83 | 956 | } else { |
| RobMeades | 0:7ccf0e7e8a83 | 957 | tr_debug("socket_recvfrom: received %d byte(s)", count); |
| RobMeades | 0:7ccf0e7e8a83 | 958 | } |
| RobMeades | 0:7ccf0e7e8a83 | 959 | |
| RobMeades | 0:7ccf0e7e8a83 | 960 | return nsapi_error_size; |
| RobMeades | 0:7ccf0e7e8a83 | 961 | } |
| RobMeades | 0:7ccf0e7e8a83 | 962 | |
| RobMeades | 0:7ccf0e7e8a83 | 963 | // Attach an event callback to a socket, required for asynchronous |
| RobMeades | 0:7ccf0e7e8a83 | 964 | // data reception |
| RobMeades | 0:7ccf0e7e8a83 | 965 | void UbloxATCellularInterface::socket_attach(nsapi_socket_t handle, |
| Curt Black |
18:bfc869299185 | 966 | void (*callback)(void *), |
| Curt Black |
18:bfc869299185 | 967 | void *data) |
| RobMeades | 0:7ccf0e7e8a83 | 968 | { |
| RobMeades | 0:7ccf0e7e8a83 | 969 | SockCtrl *socket = (SockCtrl *) handle; |
| RobMeades | 0:7ccf0e7e8a83 | 970 | |
| RobMeades | 0:7ccf0e7e8a83 | 971 | MBED_ASSERT (check_socket(socket)); |
| RobMeades | 0:7ccf0e7e8a83 | 972 | |
| RobMeades | 0:7ccf0e7e8a83 | 973 | socket->callback = callback; |
| RobMeades | 0:7ccf0e7e8a83 | 974 | socket->data = data; |
| RobMeades | 0:7ccf0e7e8a83 | 975 | } |
| RobMeades | 0:7ccf0e7e8a83 | 976 | |
| RobMeades | 0:7ccf0e7e8a83 | 977 | // Unsupported TCP server functions. |
| RobMeades | 0:7ccf0e7e8a83 | 978 | nsapi_error_t UbloxATCellularInterface::socket_listen(nsapi_socket_t handle, |
| Curt Black |
18:bfc869299185 | 979 | int backlog) |
| RobMeades | 0:7ccf0e7e8a83 | 980 | { |
| RobMeades | 0:7ccf0e7e8a83 | 981 | return NSAPI_ERROR_UNSUPPORTED; |
| RobMeades | 0:7ccf0e7e8a83 | 982 | } |
| RobMeades | 0:7ccf0e7e8a83 | 983 | nsapi_error_t UbloxATCellularInterface::socket_accept(nsapi_socket_t server, |
| Curt Black |
18:bfc869299185 | 984 | nsapi_socket_t *handle, |
| Curt Black |
18:bfc869299185 | 985 | SocketAddress *address) |
| RobMeades | 0:7ccf0e7e8a83 | 986 | { |
| RobMeades | 0:7ccf0e7e8a83 | 987 | return NSAPI_ERROR_UNSUPPORTED; |
| RobMeades | 0:7ccf0e7e8a83 | 988 | } |
| RobMeades | 0:7ccf0e7e8a83 | 989 | |
| RobMeades | 0:7ccf0e7e8a83 | 990 | // Unsupported option functions. |
| RobMeades | 0:7ccf0e7e8a83 | 991 | nsapi_error_t UbloxATCellularInterface::setsockopt(nsapi_socket_t handle, |
| Curt Black |
18:bfc869299185 | 992 | int level, int optname, |
| Curt Black |
18:bfc869299185 | 993 | const void *optval, |
| Curt Black |
18:bfc869299185 | 994 | unsigned optlen) |
| RobMeades | 0:7ccf0e7e8a83 | 995 | { |
| RobMeades | 0:7ccf0e7e8a83 | 996 | return NSAPI_ERROR_UNSUPPORTED; |
| RobMeades | 0:7ccf0e7e8a83 | 997 | } |
| RobMeades | 0:7ccf0e7e8a83 | 998 | nsapi_error_t UbloxATCellularInterface::getsockopt(nsapi_socket_t handle, |
| Curt Black |
18:bfc869299185 | 999 | int level, int optname, |
| Curt Black |
18:bfc869299185 | 1000 | void *optval, |
| Curt Black |
18:bfc869299185 | 1001 | unsigned *optlen) |
| RobMeades | 0:7ccf0e7e8a83 | 1002 | { |
| RobMeades | 0:7ccf0e7e8a83 | 1003 | return NSAPI_ERROR_UNSUPPORTED; |
| RobMeades | 0:7ccf0e7e8a83 | 1004 | } |
| RobMeades | 0:7ccf0e7e8a83 | 1005 | |
| RobMeades | 0:7ccf0e7e8a83 | 1006 | /********************************************************************** |
| RobMeades | 0:7ccf0e7e8a83 | 1007 | * PUBLIC METHODS |
| RobMeades | 0:7ccf0e7e8a83 | 1008 | **********************************************************************/ |
| RobMeades | 0:7ccf0e7e8a83 | 1009 | |
| RobMeades | 0:7ccf0e7e8a83 | 1010 | // Constructor. |
| RobMeades | 0:7ccf0e7e8a83 | 1011 | UbloxATCellularInterface::UbloxATCellularInterface(PinName tx, |
| Curt Black |
18:bfc869299185 | 1012 | PinName rx, |
| Curt Black |
18:bfc869299185 | 1013 | int baud, |
| Curt Black |
18:bfc869299185 | 1014 | bool debug_on) |
| RobMeades | 0:7ccf0e7e8a83 | 1015 | { |
| RobMeades | 0:7ccf0e7e8a83 | 1016 | _sim_pin_check_change_pending = false; |
| RobMeades | 0:7ccf0e7e8a83 | 1017 | _sim_pin_check_change_pending_enabled_value = false; |
| RobMeades | 0:7ccf0e7e8a83 | 1018 | _sim_pin_change_pending = false; |
| RobMeades | 0:7ccf0e7e8a83 | 1019 | _sim_pin_change_pending_new_pin_value = NULL; |
| RobMeades | 14:e7dcf3388403 | 1020 | _run_event_thread = true; |
| RobMeades | 0:7ccf0e7e8a83 | 1021 | _apn = NULL; |
| RobMeades | 0:7ccf0e7e8a83 | 1022 | _uname = NULL; |
| RobMeades | 0:7ccf0e7e8a83 | 1023 | _pwd = NULL; |
| RobMeades | 0:7ccf0e7e8a83 | 1024 | _connection_status_cb = NULL; |
| RobMeades | 0:7ccf0e7e8a83 | 1025 | |
| RobMeades | 0:7ccf0e7e8a83 | 1026 | // Initialise sockets storage |
| RobMeades | 0:7ccf0e7e8a83 | 1027 | memset(_sockets, 0, sizeof(_sockets)); |
| RobMeades | 0:7ccf0e7e8a83 | 1028 | for (unsigned int socket = 0; socket < sizeof(_sockets) / sizeof(_sockets[0]); socket++) { |
| RobMeades | 0:7ccf0e7e8a83 | 1029 | _sockets[socket].modem_handle = SOCKET_UNUSED; |
| RobMeades | 0:7ccf0e7e8a83 | 1030 | _sockets[socket].callback = NULL; |
| RobMeades | 0:7ccf0e7e8a83 | 1031 | _sockets[socket].data = NULL; |
| RobMeades | 0:7ccf0e7e8a83 | 1032 | } |
| RobMeades | 0:7ccf0e7e8a83 | 1033 | |
| RobMeades | 0:7ccf0e7e8a83 | 1034 | // The authentication to use |
| RobMeades | 0:7ccf0e7e8a83 | 1035 | _auth = NSAPI_SECURITY_UNKNOWN; |
| RobMeades | 0:7ccf0e7e8a83 | 1036 | |
| RobMeades | 0:7ccf0e7e8a83 | 1037 | // Nullify the temporary IP address storage |
| RobMeades | 0:7ccf0e7e8a83 | 1038 | _ip = NULL; |
| RobMeades | 0:7ccf0e7e8a83 | 1039 | |
| RobMeades | 0:7ccf0e7e8a83 | 1040 | // Initialise the base class, which starts the AT parser |
| RobMeades | 0:7ccf0e7e8a83 | 1041 | baseClassInit(tx, rx, baud, debug_on); |
| RobMeades | 0:7ccf0e7e8a83 | 1042 | |
| RobMeades | 0:7ccf0e7e8a83 | 1043 | // Start the event handler thread for Rx data |
| RobMeades | 0:7ccf0e7e8a83 | 1044 | event_thread.start(callback(this, &UbloxATCellularInterface::handle_event)); |
| RobMeades | 0:7ccf0e7e8a83 | 1045 | |
| RobMeades | 0:7ccf0e7e8a83 | 1046 | // URC handlers for sockets |
| RobMeades | 0:7ccf0e7e8a83 | 1047 | _at->oob("+UUSORD", callback(this, &UbloxATCellularInterface::UUSORD_URC)); |
| RobMeades | 0:7ccf0e7e8a83 | 1048 | _at->oob("+UUSORF", callback(this, &UbloxATCellularInterface::UUSORF_URC)); |
| RobMeades | 0:7ccf0e7e8a83 | 1049 | _at->oob("+UUSOCL", callback(this, &UbloxATCellularInterface::UUSOCL_URC)); |
| RobMeades | 0:7ccf0e7e8a83 | 1050 | _at->oob("+UUPSDD", callback(this, &UbloxATCellularInterface::UUPSDD_URC)); |
| RobMeades | 0:7ccf0e7e8a83 | 1051 | } |
| RobMeades | 0:7ccf0e7e8a83 | 1052 | |
| RobMeades | 0:7ccf0e7e8a83 | 1053 | // Destructor. |
| RobMeades | 0:7ccf0e7e8a83 | 1054 | UbloxATCellularInterface::~UbloxATCellularInterface() |
| RobMeades | 0:7ccf0e7e8a83 | 1055 | { |
| RobMeades | 14:e7dcf3388403 | 1056 | // Let the event thread shut down tidily |
| RobMeades | 14:e7dcf3388403 | 1057 | _run_event_thread = false; |
| RobMeades | 14:e7dcf3388403 | 1058 | event_thread.join(); |
| Curt Black |
18:bfc869299185 | 1059 | |
| RobMeades | 0:7ccf0e7e8a83 | 1060 | // Free _ip if it was ever allocated |
| RobMeades | 0:7ccf0e7e8a83 | 1061 | free(_ip); |
| RobMeades | 0:7ccf0e7e8a83 | 1062 | } |
| RobMeades | 0:7ccf0e7e8a83 | 1063 | |
| RobMeades | 0:7ccf0e7e8a83 | 1064 | // Set the authentication scheme. |
| RobMeades | 0:7ccf0e7e8a83 | 1065 | void UbloxATCellularInterface::set_authentication(nsapi_security_t auth) |
| RobMeades | 0:7ccf0e7e8a83 | 1066 | { |
| RobMeades | 0:7ccf0e7e8a83 | 1067 | _auth = auth; |
| RobMeades | 0:7ccf0e7e8a83 | 1068 | } |
| RobMeades | 0:7ccf0e7e8a83 | 1069 | |
| RobMeades | 0:7ccf0e7e8a83 | 1070 | // Set APN, user name and password. |
| RobMeades | 0:7ccf0e7e8a83 | 1071 | void UbloxATCellularInterface::set_credentials(const char *apn, |
| Curt Black |
18:bfc869299185 | 1072 | const char *uname, |
| Curt Black |
18:bfc869299185 | 1073 | const char *pwd) |
| RobMeades | 0:7ccf0e7e8a83 | 1074 | { |
| RobMeades | 0:7ccf0e7e8a83 | 1075 | _apn = apn; |
| RobMeades | 0:7ccf0e7e8a83 | 1076 | _uname = uname; |
| RobMeades | 0:7ccf0e7e8a83 | 1077 | _pwd = pwd; |
| RobMeades | 0:7ccf0e7e8a83 | 1078 | } |
| RobMeades | 0:7ccf0e7e8a83 | 1079 | |
| RobMeades | 0:7ccf0e7e8a83 | 1080 | // Set PIN. |
| RobMeades | 12:ff6fac481487 | 1081 | void UbloxATCellularInterface::set_sim_pin(const char *pin) |
| RobMeades | 12:ff6fac481487 | 1082 | { |
| RobMeades | 0:7ccf0e7e8a83 | 1083 | set_pin(pin); |
| RobMeades | 0:7ccf0e7e8a83 | 1084 | } |
| RobMeades | 0:7ccf0e7e8a83 | 1085 | |
| RobMeades | 0:7ccf0e7e8a83 | 1086 | // Get the IP address of a host. |
| RobMeades | 0:7ccf0e7e8a83 | 1087 | nsapi_error_t UbloxATCellularInterface::gethostbyname(const char *host, |
| Curt Black |
18:bfc869299185 | 1088 | SocketAddress *address, |
| Curt Black |
18:bfc869299185 | 1089 | nsapi_version_t version) |
| RobMeades | 0:7ccf0e7e8a83 | 1090 | { |
| RobMeades | 0:7ccf0e7e8a83 | 1091 | nsapi_error_t nsapi_error = NSAPI_ERROR_DEVICE_ERROR; |
| rob.meades@u-blox.com | 6:63dad754c267 | 1092 | int at_timeout; |
| RobMeades | 0:7ccf0e7e8a83 | 1093 | char ipAddress[NSAPI_IP_SIZE]; |
| RobMeades | 0:7ccf0e7e8a83 | 1094 | |
| RobMeades | 0:7ccf0e7e8a83 | 1095 | if (address->set_ip_address(host)) { |
| RobMeades | 0:7ccf0e7e8a83 | 1096 | nsapi_error = NSAPI_ERROR_OK; |
| RobMeades | 0:7ccf0e7e8a83 | 1097 | } else { |
| RobMeades | 0:7ccf0e7e8a83 | 1098 | LOCK(); |
| rob.meades@u-blox.com | 6:63dad754c267 | 1099 | // This interrogation can sometimes take longer than the usual 8 seconds |
| rob.meades@u-blox.com | 6:63dad754c267 | 1100 | at_timeout = _at_timeout; |
| rob.meades@u-blox.com | 6:63dad754c267 | 1101 | at_set_timeout(60000); |
| RobMeades | 0:7ccf0e7e8a83 | 1102 | memset (ipAddress, 0, sizeof (ipAddress)); // Ensure terminator |
| RobMeades | 0:7ccf0e7e8a83 | 1103 | if (_at->send("AT+UDNSRN=0,\"%s\"", host) && |
| Curt Black |
18:bfc869299185 | 1104 | _at->recv("+UDNSRN: \"%" u_stringify(NSAPI_IP_SIZE) "[^\"]\"", ipAddress) && |
| Curt Black |
18:bfc869299185 | 1105 | _at->recv("OK")) { |
| RobMeades | 0:7ccf0e7e8a83 | 1106 | if (address->set_ip_address(ipAddress)) { |
| RobMeades | 0:7ccf0e7e8a83 | 1107 | nsapi_error = NSAPI_ERROR_OK; |
| RobMeades | 0:7ccf0e7e8a83 | 1108 | } |
| RobMeades | 0:7ccf0e7e8a83 | 1109 | } |
| rob.meades@u-blox.com | 6:63dad754c267 | 1110 | at_set_timeout(at_timeout); |
| RobMeades | 0:7ccf0e7e8a83 | 1111 | UNLOCK(); |
| RobMeades | 0:7ccf0e7e8a83 | 1112 | } |
| RobMeades | 0:7ccf0e7e8a83 | 1113 | |
| RobMeades | 0:7ccf0e7e8a83 | 1114 | return nsapi_error; |
| RobMeades | 0:7ccf0e7e8a83 | 1115 | } |
| RobMeades | 0:7ccf0e7e8a83 | 1116 | |
| RobMeades | 0:7ccf0e7e8a83 | 1117 | // Make a cellular connection |
| RobMeades | 0:7ccf0e7e8a83 | 1118 | nsapi_error_t UbloxATCellularInterface::connect(const char *sim_pin, |
| Curt Black |
18:bfc869299185 | 1119 | const char *apn, |
| Curt Black |
18:bfc869299185 | 1120 | const char *uname, |
| Curt Black |
18:bfc869299185 | 1121 | const char *pwd) |
| RobMeades | 0:7ccf0e7e8a83 | 1122 | { |
| RobMeades | 0:7ccf0e7e8a83 | 1123 | nsapi_error_t nsapi_error; |
| RobMeades | 0:7ccf0e7e8a83 | 1124 | |
| RobMeades | 0:7ccf0e7e8a83 | 1125 | if (sim_pin != NULL) { |
| RobMeades | 0:7ccf0e7e8a83 | 1126 | _pin = sim_pin; |
| RobMeades | 0:7ccf0e7e8a83 | 1127 | } |
| RobMeades | 0:7ccf0e7e8a83 | 1128 | |
| RobMeades | 0:7ccf0e7e8a83 | 1129 | if (apn != NULL) { |
| RobMeades | 0:7ccf0e7e8a83 | 1130 | _apn = apn; |
| RobMeades | 0:7ccf0e7e8a83 | 1131 | } |
| RobMeades | 0:7ccf0e7e8a83 | 1132 | |
| RobMeades | 0:7ccf0e7e8a83 | 1133 | if ((uname != NULL) && (pwd != NULL)) { |
| RobMeades | 0:7ccf0e7e8a83 | 1134 | _uname = uname; |
| RobMeades | 0:7ccf0e7e8a83 | 1135 | _pwd = pwd; |
| RobMeades | 0:7ccf0e7e8a83 | 1136 | } else { |
| RobMeades | 0:7ccf0e7e8a83 | 1137 | _uname = NULL; |
| RobMeades | 0:7ccf0e7e8a83 | 1138 | _pwd = NULL; |
| RobMeades | 0:7ccf0e7e8a83 | 1139 | } |
| RobMeades | 0:7ccf0e7e8a83 | 1140 | |
| RobMeades | 0:7ccf0e7e8a83 | 1141 | nsapi_error = connect(); |
| RobMeades | 0:7ccf0e7e8a83 | 1142 | |
| RobMeades | 0:7ccf0e7e8a83 | 1143 | return nsapi_error; |
| RobMeades | 0:7ccf0e7e8a83 | 1144 | } |
| RobMeades | 0:7ccf0e7e8a83 | 1145 | |
| RobMeades | 0:7ccf0e7e8a83 | 1146 | // Make a cellular connection using the IP stack on board the cellular modem |
| RobMeades | 0:7ccf0e7e8a83 | 1147 | nsapi_error_t UbloxATCellularInterface::connect() |
| RobMeades | 0:7ccf0e7e8a83 | 1148 | { |
| RobMeades | 0:7ccf0e7e8a83 | 1149 | nsapi_error_t nsapi_error = NSAPI_ERROR_DEVICE_ERROR; |
| RobMeades | 0:7ccf0e7e8a83 | 1150 | bool registered = false; |
| RobMeades | 0:7ccf0e7e8a83 | 1151 | |
| RobMeades | 0:7ccf0e7e8a83 | 1152 | // Set up modem and then register with the network |
| RobMeades | 0:7ccf0e7e8a83 | 1153 | if (init()) { |
| RobMeades | 0:7ccf0e7e8a83 | 1154 | nsapi_error = NSAPI_ERROR_NO_CONNECTION; |
| RobMeades | 0:7ccf0e7e8a83 | 1155 | // Perform any pending SIM actions |
| RobMeades | 0:7ccf0e7e8a83 | 1156 | if (_sim_pin_check_change_pending) { |
| RobMeades | 0:7ccf0e7e8a83 | 1157 | if (!sim_pin_check_enable(_sim_pin_check_change_pending_enabled_value)) { |
| RobMeades | 0:7ccf0e7e8a83 | 1158 | nsapi_error = NSAPI_ERROR_AUTH_FAILURE; |
| RobMeades | 0:7ccf0e7e8a83 | 1159 | } |
| RobMeades | 0:7ccf0e7e8a83 | 1160 | _sim_pin_check_change_pending = false; |
| RobMeades | 0:7ccf0e7e8a83 | 1161 | } |
| RobMeades | 0:7ccf0e7e8a83 | 1162 | if (_sim_pin_change_pending) { |
| RobMeades | 0:7ccf0e7e8a83 | 1163 | if (!change_sim_pin(_sim_pin_change_pending_new_pin_value)) { |
| RobMeades | 0:7ccf0e7e8a83 | 1164 | nsapi_error = NSAPI_ERROR_AUTH_FAILURE; |
| RobMeades | 0:7ccf0e7e8a83 | 1165 | } |
| RobMeades | 0:7ccf0e7e8a83 | 1166 | _sim_pin_change_pending = false; |
| RobMeades | 0:7ccf0e7e8a83 | 1167 | } |
| RobMeades | 0:7ccf0e7e8a83 | 1168 | |
| RobMeades | 0:7ccf0e7e8a83 | 1169 | if (nsapi_error == NSAPI_ERROR_NO_CONNECTION) { |
| RobMeades | 0:7ccf0e7e8a83 | 1170 | for (int retries = 0; !registered && (retries < 3); retries++) { |
| RobMeades | 0:7ccf0e7e8a83 | 1171 | if (nwk_registration()) { |
| RobMeades | 0:7ccf0e7e8a83 | 1172 | registered = true;; |
| RobMeades | 0:7ccf0e7e8a83 | 1173 | } |
| RobMeades | 0:7ccf0e7e8a83 | 1174 | } |
| RobMeades | 0:7ccf0e7e8a83 | 1175 | } |
| RobMeades | 0:7ccf0e7e8a83 | 1176 | } |
| RobMeades | 0:7ccf0e7e8a83 | 1177 | |
| RobMeades | 0:7ccf0e7e8a83 | 1178 | // Attempt to establish a connection |
| Curt Black |
17:8696a2ecde3f | 1179 | #if defined(TARGET_UBLOX_C030_R410M) || defined (TARGET_SR_L475RG_R410) |
| RobMeades | 13:39264b492ce7 | 1180 | if (registered) { |
| RobMeades | 13:39264b492ce7 | 1181 | #else |
| Curt Black |
18:bfc869299185 | 1182 | if (registered && connect_modem_stack()) { |
| RobMeades | 13:39264b492ce7 | 1183 | #endif |
| Curt Black |
18:bfc869299185 | 1184 | nsapi_error = NSAPI_ERROR_OK; |
| Curt Black |
18:bfc869299185 | 1185 | } |
| RobMeades | 0:7ccf0e7e8a83 | 1186 | |
| Curt Black |
18:bfc869299185 | 1187 | return nsapi_error; |
| RobMeades | 0:7ccf0e7e8a83 | 1188 | } |
| RobMeades | 0:7ccf0e7e8a83 | 1189 | |
| Curt Black |
18:bfc869299185 | 1190 | // User initiated disconnect. |
| Curt Black |
18:bfc869299185 | 1191 | nsapi_error_t UbloxATCellularInterface::disconnect() |
| Curt Black |
18:bfc869299185 | 1192 | { |
| Curt Black |
18:bfc869299185 | 1193 | nsapi_error_t nsapi_error = NSAPI_ERROR_DEVICE_ERROR; |
| Curt Black |
18:bfc869299185 | 1194 | |
| Curt Black |
18:bfc869299185 | 1195 | if (disconnect_modem_stack() && nwk_deregistration()) { |
| Curt Black |
18:bfc869299185 | 1196 | nsapi_error = NSAPI_ERROR_OK; |
| RobMeades | 0:7ccf0e7e8a83 | 1197 | } |
| Curt Black |
18:bfc869299185 | 1198 | |
| Curt Black |
18:bfc869299185 | 1199 | return nsapi_error; |
| RobMeades | 0:7ccf0e7e8a83 | 1200 | } |
| RobMeades | 0:7ccf0e7e8a83 | 1201 | |
| Curt Black |
18:bfc869299185 | 1202 | // Enable or disable SIM PIN check lock. |
| Curt Black |
18:bfc869299185 | 1203 | nsapi_error_t UbloxATCellularInterface::set_sim_pin_check(bool set, |
| Curt Black |
18:bfc869299185 | 1204 | bool immediate, |
| Curt Black |
18:bfc869299185 | 1205 | const char *sim_pin) |
| Curt Black |
18:bfc869299185 | 1206 | { |
| Curt Black |
18:bfc869299185 | 1207 | nsapi_error_t nsapi_error = NSAPI_ERROR_AUTH_FAILURE; |
| RobMeades | 0:7ccf0e7e8a83 | 1208 | |
| Curt Black |
18:bfc869299185 | 1209 | if (sim_pin != NULL) { |
| Curt Black |
18:bfc869299185 | 1210 | _pin = sim_pin; |
| Curt Black |
18:bfc869299185 | 1211 | } |
| RobMeades | 0:7ccf0e7e8a83 | 1212 | |
| Curt Black |
18:bfc869299185 | 1213 | if (immediate) { |
| Curt Black |
18:bfc869299185 | 1214 | if (init()) { |
| Curt Black |
18:bfc869299185 | 1215 | if (sim_pin_check_enable(set)) { |
| Curt Black |
18:bfc869299185 | 1216 | nsapi_error = NSAPI_ERROR_OK; |
| Curt Black |
18:bfc869299185 | 1217 | } |
| Curt Black |
18:bfc869299185 | 1218 | } else { |
| Curt Black |
18:bfc869299185 | 1219 | nsapi_error = NSAPI_ERROR_DEVICE_ERROR; |
| RobMeades | 0:7ccf0e7e8a83 | 1220 | } |
| RobMeades | 0:7ccf0e7e8a83 | 1221 | } else { |
| Curt Black |
18:bfc869299185 | 1222 | nsapi_error = NSAPI_ERROR_OK; |
| Curt Black |
18:bfc869299185 | 1223 | _sim_pin_check_change_pending = true; |
| Curt Black |
18:bfc869299185 | 1224 | _sim_pin_check_change_pending_enabled_value = set; |
| RobMeades | 0:7ccf0e7e8a83 | 1225 | } |
| Curt Black |
18:bfc869299185 | 1226 | |
| Curt Black |
18:bfc869299185 | 1227 | return nsapi_error; |
| RobMeades | 0:7ccf0e7e8a83 | 1228 | } |
| RobMeades | 0:7ccf0e7e8a83 | 1229 | |
| Curt Black |
18:bfc869299185 | 1230 | // Change the PIN code for the SIM card. |
| Curt Black |
18:bfc869299185 | 1231 | nsapi_error_t UbloxATCellularInterface::set_new_sim_pin(const char *new_pin, |
| Curt Black |
18:bfc869299185 | 1232 | bool immediate, |
| Curt Black |
18:bfc869299185 | 1233 | const char *old_pin) |
| Curt Black |
18:bfc869299185 | 1234 | { |
| Curt Black |
18:bfc869299185 | 1235 | nsapi_error_t nsapi_error = NSAPI_ERROR_AUTH_FAILURE; |
| RobMeades | 0:7ccf0e7e8a83 | 1236 | |
| Curt Black |
18:bfc869299185 | 1237 | if (old_pin != NULL) { |
| Curt Black |
18:bfc869299185 | 1238 | _pin = old_pin; |
| Curt Black |
18:bfc869299185 | 1239 | } |
| RobMeades | 0:7ccf0e7e8a83 | 1240 | |
| Curt Black |
18:bfc869299185 | 1241 | if (immediate) { |
| Curt Black |
18:bfc869299185 | 1242 | if (init()) { |
| Curt Black |
18:bfc869299185 | 1243 | if (change_sim_pin(new_pin)) { |
| Curt Black |
18:bfc869299185 | 1244 | nsapi_error = NSAPI_ERROR_OK; |
| Curt Black |
18:bfc869299185 | 1245 | } |
| Curt Black |
18:bfc869299185 | 1246 | } else { |
| Curt Black |
18:bfc869299185 | 1247 | nsapi_error = NSAPI_ERROR_DEVICE_ERROR; |
| Curt Black |
18:bfc869299185 | 1248 | } |
| Curt Black |
18:bfc869299185 | 1249 | } else { |
| Curt Black |
18:bfc869299185 | 1250 | nsapi_error = NSAPI_ERROR_OK; |
| Curt Black |
18:bfc869299185 | 1251 | _sim_pin_change_pending = true; |
| Curt Black |
18:bfc869299185 | 1252 | _sim_pin_change_pending_new_pin_value = new_pin; |
| Curt Black |
18:bfc869299185 | 1253 | } |
| RobMeades | 0:7ccf0e7e8a83 | 1254 | |
| Curt Black |
18:bfc869299185 | 1255 | return nsapi_error; |
| Curt Black |
18:bfc869299185 | 1256 | } |
| Curt Black |
18:bfc869299185 | 1257 | |
| Curt Black |
18:bfc869299185 | 1258 | // Determine if the connection is up. |
| Curt Black |
18:bfc869299185 | 1259 | bool UbloxATCellularInterface::is_connected() |
| Curt Black |
18:bfc869299185 | 1260 | { |
| Curt Black |
18:bfc869299185 | 1261 | return get_ip_address() != NULL; |
| RobMeades | 0:7ccf0e7e8a83 | 1262 | } |
| RobMeades | 0:7ccf0e7e8a83 | 1263 | |
| Curt Black |
18:bfc869299185 | 1264 | // Get the IP address of the on-board modem IP stack. |
| Curt Black |
18:bfc869299185 | 1265 | const char * UbloxATCellularInterface::get_ip_address() |
| Curt Black |
18:bfc869299185 | 1266 | { |
| Curt Black |
18:bfc869299185 | 1267 | SocketAddress address; |
| Curt Black |
18:bfc869299185 | 1268 | LOCK(); |
| Curt Black |
18:bfc869299185 | 1269 | |
| Curt Black |
18:bfc869299185 | 1270 | if (_ip == NULL) { |
| Curt Black |
18:bfc869299185 | 1271 | // Temporary storage for an IP address string with terminator |
| Curt Black |
18:bfc869299185 | 1272 | _ip = (char *) malloc(NSAPI_IP_SIZE); |
| RobMeades | 0:7ccf0e7e8a83 | 1273 | } |
| Curt Black |
18:bfc869299185 | 1274 | |
| Curt Black |
18:bfc869299185 | 1275 | if (_ip != NULL) { |
| Curt Black |
18:bfc869299185 | 1276 | memset(_ip, 0, NSAPI_IP_SIZE); // Ensure a terminator |
| Curt Black |
18:bfc869299185 | 1277 | // +UPSND=<profile_id>,<param_tag>[,<dynamic_param_val>] |
| Curt Black |
18:bfc869299185 | 1278 | // If we get back a quoted "w.x.y.z" then we have an IP address, |
| Curt Black |
18:bfc869299185 | 1279 | // otherwise we don't. |
| Curt Black |
18:bfc869299185 | 1280 | if (!_at->send("AT+UPSND=" PROFILE ",0") || |
| Curt Black |
18:bfc869299185 | 1281 | !_at->recv("+UPSND: " PROFILE ",0,\"%" u_stringify(NSAPI_IP_SIZE) "[^\"]\"", _ip) || |
| Curt Black |
18:bfc869299185 | 1282 | !_at->recv("OK") || |
| Curt Black |
18:bfc869299185 | 1283 | !address.set_ip_address(_ip) || // Return NULL if the address is not a valid one |
| Curt Black |
18:bfc869299185 | 1284 | !address) { // Return null if the address is zero |
| Curt Black |
18:bfc869299185 | 1285 | free (_ip); |
| Curt Black |
18:bfc869299185 | 1286 | _ip = NULL; |
| Curt Black |
18:bfc869299185 | 1287 | } |
| Curt Black |
18:bfc869299185 | 1288 | } |
| Curt Black |
18:bfc869299185 | 1289 | |
| Curt Black |
18:bfc869299185 | 1290 | UNLOCK(); |
| Curt Black |
18:bfc869299185 | 1291 | return _ip; |
| RobMeades | 0:7ccf0e7e8a83 | 1292 | } |
| RobMeades | 0:7ccf0e7e8a83 | 1293 | |
| Curt Black |
18:bfc869299185 | 1294 | // Get the local network mask. |
| Curt Black |
18:bfc869299185 | 1295 | const char *UbloxATCellularInterface::get_netmask() |
| Curt Black |
18:bfc869299185 | 1296 | { |
| Curt Black |
18:bfc869299185 | 1297 | // Not implemented. |
| Curt Black |
18:bfc869299185 | 1298 | return NULL; |
| Curt Black |
18:bfc869299185 | 1299 | } |
| RobMeades | 0:7ccf0e7e8a83 | 1300 | |
| Curt Black |
18:bfc869299185 | 1301 | // Get the local gateways. |
| Curt Black |
18:bfc869299185 | 1302 | const char *UbloxATCellularInterface::get_gateway() |
| Curt Black |
18:bfc869299185 | 1303 | { |
| Curt Black |
18:bfc869299185 | 1304 | return get_ip_address(); |
| Curt Black |
18:bfc869299185 | 1305 | } |
| RobMeades | 0:7ccf0e7e8a83 | 1306 | |
| Curt Black |
18:bfc869299185 | 1307 | // Callback in case the connection is lost. |
| Curt Black |
18:bfc869299185 | 1308 | void UbloxATCellularInterface::connection_status_cb(Callback<void(nsapi_error_t)> cb) |
| Curt Black |
18:bfc869299185 | 1309 | { |
| Curt Black |
18:bfc869299185 | 1310 | _connection_status_cb = cb; |
| Curt Black |
18:bfc869299185 | 1311 | } |
| RobMeades | 0:7ccf0e7e8a83 | 1312 | |
| Curt Black |
18:bfc869299185 | 1313 | // End of file |
| RobMeades | 0:7ccf0e7e8a83 | 1314 |
