Implementation of the CellularInterface for u-blox C027 and C030 (non-N2xx flavour) modems that uses the IP stack on-board the cellular modem, hence not requiring LWIP (and so less RAM) and allowing any AT command exchanges to be carried out at the same time as data transfers (since the modem remains in AT mode all the time). This library may be used from mbed 5.5 onwards. If you need to use SMS, USSD or access the modem file system at the same time as using the CellularInterface then use ublox-at-cellular-interface-ext instead.

Dependents:   example-ublox-cellular-interface example-ublox-cellular-interface_r410M example-ublox-mbed-client example-ublox-cellular-interface ... more

Committer:
RobMeades
Date:
Mon Jun 12 21:32:21 2017 +0000
Revision:
0:7ccf0e7e8a83
Child:
1:bc228becc45d
Initial commit, not yet compiling but I'm tired of doing everything in the on-line IDE so I need to publish to take the code off-line.

Who changed what in which revision?

UserRevisionLine numberNew 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
RobMeades 0:7ccf0e7e8a83 24 #define tr_debug(format, ...) debug(format, ## __VA_ARGS__)
RobMeades 0:7ccf0e7e8a83 25 #define tr_info(format, ...) debug(format, ## __VA_ARGS__)
RobMeades 0:7ccf0e7e8a83 26 #define tr_warn(format, ...) debug(format, ## __VA_ARGS__)
RobMeades 0:7ccf0e7e8a83 27 #define tr_error(format, ...) debug(format, ## __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 0:7ccf0e7e8a83 43 while (true) {
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
RobMeades 0:7ccf0e7e8a83 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 {
RobMeades 0:7ccf0e7e8a83 108 case NSAPI_SECURITY_NONE:
RobMeades 0:7ccf0e7e8a83 109 modem_security = 0;
RobMeades 0:7ccf0e7e8a83 110 break;
RobMeades 0:7ccf0e7e8a83 111 case NSAPI_SECURITY_PAP:
RobMeades 0:7ccf0e7e8a83 112 modem_security = 1;
RobMeades 0:7ccf0e7e8a83 113 break;
RobMeades 0:7ccf0e7e8a83 114 case NSAPI_SECURITY_CHAP:
RobMeades 0:7ccf0e7e8a83 115 modem_security = 2;
RobMeades 0:7ccf0e7e8a83 116 break;
RobMeades 0:7ccf0e7e8a83 117 case NSAPI_SECURITY_UNKNOWN:
RobMeades 0:7ccf0e7e8a83 118 modem_security = 3;
RobMeades 0:7ccf0e7e8a83 119 break;
RobMeades 0:7ccf0e7e8a83 120 default:
RobMeades 0:7ccf0e7e8a83 121 modem_security = 3;
RobMeades 0:7ccf0e7e8a83 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",
RobMeades 0:7ccf0e7e8a83 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",
RobMeades 0:7ccf0e7e8a83 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.
RobMeades 0:7ccf0e7e8a83 228 void UbloxATCellularInterface::get_next_credentials(const char * config)
RobMeades 0:7ccf0e7e8a83 229 {
RobMeades 0:7ccf0e7e8a83 230 if (config) {
RobMeades 0:7ccf0e7e8a83 231 _apn = _APN_GET(config);
RobMeades 0:7ccf0e7e8a83 232 _uname = _APN_GET(config);
RobMeades 0:7ccf0e7e8a83 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,
RobMeades 0:7ccf0e7e8a83 244 const char* username,
RobMeades 0:7ccf0e7e8a83 245 const char* password,
RobMeades 0:7ccf0e7e8a83 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);
RobMeades 0:7ccf0e7e8a83 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",
RobMeades 0:7ccf0e7e8a83 301 &t, ip) &&
RobMeades 0:7ccf0e7e8a83 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,
RobMeades 0:7ccf0e7e8a83 324 const char* apn,
RobMeades 0:7ccf0e7e8a83 325 const char* username,
RobMeades 0:7ccf0e7e8a83 326 const char* password,
RobMeades 0:7ccf0e7e8a83 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
RobMeades 0:7ccf0e7e8a83 332 if (_at->send("AT+CGDCONT=%d,\"IP\",\"%s\"", cid, apn) && _at->recv("OK") &&
RobMeades 0:7ccf0e7e8a83 333 _at->send("AT+UAUTHREQ=%d,%d,\"%s\",\"%s\"", cid, nsapi_security_to_modem_security(auth),
RobMeades 0:7ccf0e7e8a83 334 username, password) && _at->recv("OK") &&
RobMeades 0:7ccf0e7e8a83 335 _at->send("AT+UPSD=" PROFILE ",100,%d", cid) && _at->recv("OK")) {
RobMeades 0:7ccf0e7e8a83 336
RobMeades 0:7ccf0e7e8a83 337 // Wait 30 seconds for the connection to be made
RobMeades 0:7ccf0e7e8a83 338 at_set_timeout(30000);
RobMeades 0:7ccf0e7e8a83 339 // Activate the protocol
RobMeades 0:7ccf0e7e8a83 340 success = _at->send("AT+UPSDA=" PROFILE ",3") && _at->recv("OK");
RobMeades 0:7ccf0e7e8a83 341 at_set_timeout(at_timeout);
RobMeades 0:7ccf0e7e8a83 342 }
RobMeades 0:7ccf0e7e8a83 343
RobMeades 0:7ccf0e7e8a83 344 return success;
RobMeades 0:7ccf0e7e8a83 345 }
RobMeades 0:7ccf0e7e8a83 346
RobMeades 0:7ccf0e7e8a83 347 // Connect the on board IP stack of the modem.
RobMeades 0:7ccf0e7e8a83 348 bool UbloxATCellularInterface::connect_modem_stack()
RobMeades 0:7ccf0e7e8a83 349 {
RobMeades 0:7ccf0e7e8a83 350 bool success = false;
RobMeades 0:7ccf0e7e8a83 351 int active = 0;
RobMeades 0:7ccf0e7e8a83 352 const char * config = NULL;
RobMeades 0:7ccf0e7e8a83 353 LOCK();
RobMeades 0:7ccf0e7e8a83 354
RobMeades 0:7ccf0e7e8a83 355 // Check the profile
RobMeades 0:7ccf0e7e8a83 356 if (_at->send("AT+UPSND=" PROFILE ",8") && _at->recv("+UPSND: %*d,%*d,%d\n", &active) &&
RobMeades 0:7ccf0e7e8a83 357 _at->recv("OK")) {
RobMeades 0:7ccf0e7e8a83 358 if (active == 0) {
RobMeades 0:7ccf0e7e8a83 359 // If the caller hasn't entered an APN, try to find it
RobMeades 0:7ccf0e7e8a83 360 if (_apn == NULL) {
RobMeades 0:7ccf0e7e8a83 361 config = apnconfig(_dev_info.imsi);
RobMeades 0:7ccf0e7e8a83 362 }
RobMeades 0:7ccf0e7e8a83 363
RobMeades 0:7ccf0e7e8a83 364 // Attempt to connect
RobMeades 0:7ccf0e7e8a83 365 do {
RobMeades 0:7ccf0e7e8a83 366 // Set up APN and IP protocol for PDP context
RobMeades 0:7ccf0e7e8a83 367 get_next_credentials(config);
RobMeades 0:7ccf0e7e8a83 368 _auth = (*_uname && *_pwd) ? _auth : NSAPI_SECURITY_NONE;
RobMeades 0:7ccf0e7e8a83 369 if ((_dev_info.dev != DEV_TOBY_L2) && (_dev_info.dev != DEV_MPCI_L2)) {
RobMeades 0:7ccf0e7e8a83 370 success = activate_profile(_apn, _uname, _pwd, _auth);
RobMeades 0:7ccf0e7e8a83 371 } else {
RobMeades 0:7ccf0e7e8a83 372 success = activate_profile_reuse_external();
RobMeades 0:7ccf0e7e8a83 373 if (success) {
RobMeades 0:7ccf0e7e8a83 374 tr_debug("Reusing external context");
RobMeades 0:7ccf0e7e8a83 375 } else {
RobMeades 0:7ccf0e7e8a83 376 success = activate_profile_by_cid(1, _apn, _uname, _pwd, _auth);
RobMeades 0:7ccf0e7e8a83 377 }
RobMeades 0:7ccf0e7e8a83 378 }
RobMeades 0:7ccf0e7e8a83 379 } while (!success && config && *config);
RobMeades 0:7ccf0e7e8a83 380 } else {
RobMeades 0:7ccf0e7e8a83 381 // If the profile is already active, we're good
RobMeades 0:7ccf0e7e8a83 382 success = true;
RobMeades 0:7ccf0e7e8a83 383 }
RobMeades 0:7ccf0e7e8a83 384 }
RobMeades 0:7ccf0e7e8a83 385
RobMeades 0:7ccf0e7e8a83 386 if (!success) {
RobMeades 0:7ccf0e7e8a83 387 tr_error("Failed to connect, check your APN/username/password");
RobMeades 0:7ccf0e7e8a83 388 }
RobMeades 0:7ccf0e7e8a83 389
RobMeades 0:7ccf0e7e8a83 390 UNLOCK();
RobMeades 0:7ccf0e7e8a83 391 return success;
RobMeades 0:7ccf0e7e8a83 392 }
RobMeades 0:7ccf0e7e8a83 393
RobMeades 0:7ccf0e7e8a83 394 // Disconnect the on board IP stack of the modem.
RobMeades 0:7ccf0e7e8a83 395 bool UbloxATCellularInterface::disconnect_modem_stack()
RobMeades 0:7ccf0e7e8a83 396 {
RobMeades 0:7ccf0e7e8a83 397 bool success = false;
RobMeades 0:7ccf0e7e8a83 398 LOCK();
RobMeades 0:7ccf0e7e8a83 399
RobMeades 0:7ccf0e7e8a83 400 if (get_ip_address() != NULL) {
RobMeades 0:7ccf0e7e8a83 401 if (_at->send("AT+UPSDA=" PROFILE ",4") && _at->recv("OK")) {
RobMeades 0:7ccf0e7e8a83 402 success = true;
RobMeades 0:7ccf0e7e8a83 403 if (_connection_status_cb) {
RobMeades 0:7ccf0e7e8a83 404 _connection_status_cb(NSAPI_ERROR_CONNECTION_LOST);
RobMeades 0:7ccf0e7e8a83 405 }
RobMeades 0:7ccf0e7e8a83 406 }
RobMeades 0:7ccf0e7e8a83 407 }
RobMeades 0:7ccf0e7e8a83 408
RobMeades 0:7ccf0e7e8a83 409 UNLOCK();
RobMeades 0:7ccf0e7e8a83 410 return success;
RobMeades 0:7ccf0e7e8a83 411 }
RobMeades 0:7ccf0e7e8a83 412
RobMeades 0:7ccf0e7e8a83 413 /**********************************************************************
RobMeades 0:7ccf0e7e8a83 414 * PROTECTED METHODS: NETWORK INTERFACE and SOCKETS
RobMeades 0:7ccf0e7e8a83 415 **********************************************************************/
RobMeades 0:7ccf0e7e8a83 416
RobMeades 0:7ccf0e7e8a83 417 // Gain access to us.
RobMeades 0:7ccf0e7e8a83 418 NetworkStack *UbloxATCellularInterface::get_stack()
RobMeades 0:7ccf0e7e8a83 419 {
RobMeades 0:7ccf0e7e8a83 420 return this;
RobMeades 0:7ccf0e7e8a83 421 }
RobMeades 0:7ccf0e7e8a83 422
RobMeades 0:7ccf0e7e8a83 423 // Create a socket.
RobMeades 0:7ccf0e7e8a83 424 nsapi_error_t UbloxATCellularInterface::socket_open(nsapi_socket_t *handle,
RobMeades 0:7ccf0e7e8a83 425 nsapi_protocol_t proto)
RobMeades 0:7ccf0e7e8a83 426 {
RobMeades 0:7ccf0e7e8a83 427 nsapi_error_t nsapi_error = NSAPI_ERROR_DEVICE_ERROR;
RobMeades 0:7ccf0e7e8a83 428 bool success = false;
RobMeades 0:7ccf0e7e8a83 429 int modem_handle;
RobMeades 0:7ccf0e7e8a83 430 SockCtrl *socket;
RobMeades 0:7ccf0e7e8a83 431 LOCK();
RobMeades 0:7ccf0e7e8a83 432
RobMeades 0:7ccf0e7e8a83 433 // Find a free socket
RobMeades 0:7ccf0e7e8a83 434 socket = find_socket();
RobMeades 0:7ccf0e7e8a83 435 tr_debug("socket_open(%d)", proto);
RobMeades 0:7ccf0e7e8a83 436
RobMeades 0:7ccf0e7e8a83 437 if (socket != NULL) {
RobMeades 0:7ccf0e7e8a83 438 if (proto == NSAPI_UDP) {
RobMeades 0:7ccf0e7e8a83 439 success = _at->send("AT+USOCR=17");
RobMeades 0:7ccf0e7e8a83 440 } else if (proto == NSAPI_TCP) {
RobMeades 0:7ccf0e7e8a83 441 success = _at->send("AT+USOCR=6");
RobMeades 0:7ccf0e7e8a83 442 } else {
RobMeades 0:7ccf0e7e8a83 443 nsapi_error = NSAPI_ERROR_UNSUPPORTED;
RobMeades 0:7ccf0e7e8a83 444 }
RobMeades 0:7ccf0e7e8a83 445
RobMeades 0:7ccf0e7e8a83 446 if (success) {
RobMeades 0:7ccf0e7e8a83 447 nsapi_error = NSAPI_ERROR_NO_SOCKET;
RobMeades 0:7ccf0e7e8a83 448 if (_at->recv("+USOCR: %d\n", &modem_handle) && (modem_handle != SOCKET_UNUSED) &&
RobMeades 0:7ccf0e7e8a83 449 _at->recv("OK")) {
RobMeades 0:7ccf0e7e8a83 450 tr_debug("Socket 0x%8x: handle %d was created", (unsigned int) socket, modem_handle);
RobMeades 0:7ccf0e7e8a83 451 clear_socket(socket);
RobMeades 0:7ccf0e7e8a83 452 socket->modem_handle = modem_handle;
RobMeades 0:7ccf0e7e8a83 453 *handle = (nsapi_socket_t) socket;
RobMeades 0:7ccf0e7e8a83 454 nsapi_error = NSAPI_ERROR_OK;
RobMeades 0:7ccf0e7e8a83 455 }
RobMeades 0:7ccf0e7e8a83 456 }
RobMeades 0:7ccf0e7e8a83 457 } else {
RobMeades 0:7ccf0e7e8a83 458 nsapi_error = NSAPI_ERROR_NO_MEMORY;
RobMeades 0:7ccf0e7e8a83 459 }
RobMeades 0:7ccf0e7e8a83 460
RobMeades 0:7ccf0e7e8a83 461 UNLOCK();
RobMeades 0:7ccf0e7e8a83 462 return nsapi_error;
RobMeades 0:7ccf0e7e8a83 463 }
RobMeades 0:7ccf0e7e8a83 464
RobMeades 0:7ccf0e7e8a83 465 // Close a socket.
RobMeades 0:7ccf0e7e8a83 466 nsapi_error_t UbloxATCellularInterface::socket_close(nsapi_socket_t handle)
RobMeades 0:7ccf0e7e8a83 467 {
RobMeades 0:7ccf0e7e8a83 468 nsapi_error_t nsapi_error = NSAPI_ERROR_DEVICE_ERROR;
RobMeades 0:7ccf0e7e8a83 469 SockCtrl *socket = (SockCtrl *) handle;
RobMeades 0:7ccf0e7e8a83 470 LOCK();
RobMeades 0:7ccf0e7e8a83 471
RobMeades 0:7ccf0e7e8a83 472 tr_debug("socket_close(0x%08x)", (unsigned int) handle);
RobMeades 0:7ccf0e7e8a83 473
RobMeades 0:7ccf0e7e8a83 474 MBED_ASSERT (check_socket(socket));
RobMeades 0:7ccf0e7e8a83 475
RobMeades 0:7ccf0e7e8a83 476 if (_at->send("AT+USOCL=%d", socket->modem_handle) &&
RobMeades 0:7ccf0e7e8a83 477 _at->recv("OK")) {
RobMeades 0:7ccf0e7e8a83 478 clear_socket(socket);
RobMeades 0:7ccf0e7e8a83 479 nsapi_error = NSAPI_ERROR_OK;
RobMeades 0:7ccf0e7e8a83 480 }
RobMeades 0:7ccf0e7e8a83 481
RobMeades 0:7ccf0e7e8a83 482 UNLOCK();
RobMeades 0:7ccf0e7e8a83 483 return nsapi_error;
RobMeades 0:7ccf0e7e8a83 484 }
RobMeades 0:7ccf0e7e8a83 485
RobMeades 0:7ccf0e7e8a83 486 // Bind a local port to a socket.
RobMeades 0:7ccf0e7e8a83 487 nsapi_error_t UbloxATCellularInterface::socket_bind(nsapi_socket_t handle,
RobMeades 0:7ccf0e7e8a83 488 const SocketAddress &address)
RobMeades 0:7ccf0e7e8a83 489 {
RobMeades 0:7ccf0e7e8a83 490 nsapi_error_t nsapi_error = NSAPI_ERROR_NO_SOCKET;
RobMeades 0:7ccf0e7e8a83 491 int proto;
RobMeades 0:7ccf0e7e8a83 492 int modem_handle;
RobMeades 0:7ccf0e7e8a83 493 SockCtrl savedSocket;
RobMeades 0:7ccf0e7e8a83 494 SockCtrl *socket = (SockCtrl *) handle;
RobMeades 0:7ccf0e7e8a83 495 LOCK();
RobMeades 0:7ccf0e7e8a83 496
RobMeades 0:7ccf0e7e8a83 497 tr_debug("socket_bind(0x%08x, :%d)", (unsigned int) handle, address.get_port());
RobMeades 0:7ccf0e7e8a83 498
RobMeades 0:7ccf0e7e8a83 499 MBED_ASSERT (check_socket(socket));
RobMeades 0:7ccf0e7e8a83 500
RobMeades 0:7ccf0e7e8a83 501 // Query the socket type
RobMeades 0:7ccf0e7e8a83 502 if (_at->send("AT+USOCTL=%d,0", socket->modem_handle) &&
RobMeades 0:7ccf0e7e8a83 503 _at->recv("+USOCTL: %*d,0,%d\n", &proto) &&
RobMeades 0:7ccf0e7e8a83 504 _at->recv("OK")) {
RobMeades 0:7ccf0e7e8a83 505 savedSocket = *socket;
RobMeades 0:7ccf0e7e8a83 506 nsapi_error = NSAPI_ERROR_DEVICE_ERROR;
RobMeades 0:7ccf0e7e8a83 507 // Now close the socket and re-open it with the binding given
RobMeades 0:7ccf0e7e8a83 508 if (_at->send("AT+USOCL=%d", socket->modem_handle) &&
RobMeades 0:7ccf0e7e8a83 509 _at->recv("OK")) {
RobMeades 0:7ccf0e7e8a83 510 clear_socket(socket);
RobMeades 0:7ccf0e7e8a83 511 nsapi_error = NSAPI_ERROR_CONNECTION_LOST;
RobMeades 0:7ccf0e7e8a83 512 if (_at->send("AT+USOCR=%d,%d", proto, address.get_port()) &&
RobMeades 0:7ccf0e7e8a83 513 _at->recv("+USOCR: %d\n", &modem_handle) && (modem_handle != SOCKET_UNUSED) &&
RobMeades 0:7ccf0e7e8a83 514 _at->recv("OK")) {
RobMeades 0:7ccf0e7e8a83 515 *socket = savedSocket;
RobMeades 0:7ccf0e7e8a83 516 nsapi_error = NSAPI_ERROR_OK;
RobMeades 0:7ccf0e7e8a83 517 }
RobMeades 0:7ccf0e7e8a83 518 }
RobMeades 0:7ccf0e7e8a83 519 }
RobMeades 0:7ccf0e7e8a83 520
RobMeades 0:7ccf0e7e8a83 521 UNLOCK();
RobMeades 0:7ccf0e7e8a83 522 return nsapi_error;
RobMeades 0:7ccf0e7e8a83 523 }
RobMeades 0:7ccf0e7e8a83 524
RobMeades 0:7ccf0e7e8a83 525 // Connect to a socket
RobMeades 0:7ccf0e7e8a83 526 nsapi_error_t UbloxATCellularInterface::socket_connect(nsapi_socket_t handle,
RobMeades 0:7ccf0e7e8a83 527 const SocketAddress &address)
RobMeades 0:7ccf0e7e8a83 528 {
RobMeades 0:7ccf0e7e8a83 529 nsapi_error_t nsapi_error = NSAPI_ERROR_DEVICE_ERROR;
RobMeades 0:7ccf0e7e8a83 530 SockCtrl *socket = (SockCtrl *) handle;
RobMeades 0:7ccf0e7e8a83 531 LOCK();
RobMeades 0:7ccf0e7e8a83 532
RobMeades 0:7ccf0e7e8a83 533 tr_debug("socket_connect(0x%08x, %s(:%d))", (unsigned int) handle,
RobMeades 0:7ccf0e7e8a83 534 address.get_ip_address(), address.get_port());
RobMeades 0:7ccf0e7e8a83 535
RobMeades 0:7ccf0e7e8a83 536 MBED_ASSERT (check_socket(socket));
RobMeades 0:7ccf0e7e8a83 537
RobMeades 0:7ccf0e7e8a83 538 if (_at->send("AT+USOCO=%d,\"%s\",%d", socket->modem_handle,
RobMeades 0:7ccf0e7e8a83 539 address.get_ip_address(), address.get_port()) &&
RobMeades 0:7ccf0e7e8a83 540 _at->recv("OK")) {
RobMeades 0:7ccf0e7e8a83 541 nsapi_error = NSAPI_ERROR_OK;
RobMeades 0:7ccf0e7e8a83 542 }
RobMeades 0:7ccf0e7e8a83 543
RobMeades 0:7ccf0e7e8a83 544 UNLOCK();
RobMeades 0:7ccf0e7e8a83 545 return nsapi_error;
RobMeades 0:7ccf0e7e8a83 546 }
RobMeades 0:7ccf0e7e8a83 547
RobMeades 0:7ccf0e7e8a83 548 // Send to a socket.
RobMeades 0:7ccf0e7e8a83 549 nsapi_size_or_error_t UbloxATCellularInterface::socket_send(nsapi_socket_t handle,
RobMeades 0:7ccf0e7e8a83 550 const void *data,
RobMeades 0:7ccf0e7e8a83 551 nsapi_size_t size)
RobMeades 0:7ccf0e7e8a83 552 {
RobMeades 0:7ccf0e7e8a83 553 nsapi_size_or_error_t nsapi_error_size = NSAPI_ERROR_DEVICE_ERROR;
RobMeades 0:7ccf0e7e8a83 554 bool success = true;
RobMeades 0:7ccf0e7e8a83 555 const char *buf = (const char *) data;
RobMeades 0:7ccf0e7e8a83 556 nsapi_size_t blk = MAX_WRITE_SIZE;
RobMeades 0:7ccf0e7e8a83 557 nsapi_size_t count = size;
RobMeades 0:7ccf0e7e8a83 558 SockCtrl *socket = (SockCtrl *) handle;
RobMeades 0:7ccf0e7e8a83 559
RobMeades 0:7ccf0e7e8a83 560 tr_debug("socket_send(0x%08x, 0x%08x, %d)", (unsigned int) handle, (unsigned int) data, size);
RobMeades 0:7ccf0e7e8a83 561
RobMeades 0:7ccf0e7e8a83 562 MBED_ASSERT (check_socket(socket));
RobMeades 0:7ccf0e7e8a83 563
RobMeades 0:7ccf0e7e8a83 564 while ((count > 0) && success) {
RobMeades 0:7ccf0e7e8a83 565 if (count < blk) {
RobMeades 0:7ccf0e7e8a83 566 blk = count;
RobMeades 0:7ccf0e7e8a83 567 }
RobMeades 0:7ccf0e7e8a83 568 LOCK();
RobMeades 0:7ccf0e7e8a83 569
RobMeades 0:7ccf0e7e8a83 570 if (_at->send("AT+USOWR=%d,%d", socket->modem_handle, blk) && _at->recv("@")) {
RobMeades 0:7ccf0e7e8a83 571 wait_ms(50);
RobMeades 0:7ccf0e7e8a83 572 if ((_at->write(buf, blk) < (int) blk) ||
RobMeades 0:7ccf0e7e8a83 573 !_at->recv("OK")) {
RobMeades 0:7ccf0e7e8a83 574 success = false;
RobMeades 0:7ccf0e7e8a83 575 }
RobMeades 0:7ccf0e7e8a83 576 } else {
RobMeades 0:7ccf0e7e8a83 577 success = false;
RobMeades 0:7ccf0e7e8a83 578 }
RobMeades 0:7ccf0e7e8a83 579
RobMeades 0:7ccf0e7e8a83 580 UNLOCK();
RobMeades 0:7ccf0e7e8a83 581 buf += blk;
RobMeades 0:7ccf0e7e8a83 582 count -= blk;
RobMeades 0:7ccf0e7e8a83 583 }
RobMeades 0:7ccf0e7e8a83 584
RobMeades 0:7ccf0e7e8a83 585 if (success) {
RobMeades 0:7ccf0e7e8a83 586 nsapi_error_size = size - count;
RobMeades 0:7ccf0e7e8a83 587 if (_debug_trace_on) {
RobMeades 0:7ccf0e7e8a83 588 tr_debug("socket_send: %d \"%*.*s\"", size, size, size, (char *) data);
RobMeades 0:7ccf0e7e8a83 589 }
RobMeades 0:7ccf0e7e8a83 590 }
RobMeades 0:7ccf0e7e8a83 591
RobMeades 0:7ccf0e7e8a83 592 return nsapi_error_size;
RobMeades 0:7ccf0e7e8a83 593 }
RobMeades 0:7ccf0e7e8a83 594
RobMeades 0:7ccf0e7e8a83 595 // Send to an IP address.
RobMeades 0:7ccf0e7e8a83 596 nsapi_size_or_error_t UbloxATCellularInterface::socket_sendto(nsapi_socket_t handle,
RobMeades 0:7ccf0e7e8a83 597 const SocketAddress &address,
RobMeades 0:7ccf0e7e8a83 598 const void *data,
RobMeades 0:7ccf0e7e8a83 599 nsapi_size_t size)
RobMeades 0:7ccf0e7e8a83 600 {
RobMeades 0:7ccf0e7e8a83 601 nsapi_size_or_error_t nsapi_error_size = NSAPI_ERROR_DEVICE_ERROR;
RobMeades 0:7ccf0e7e8a83 602 bool success = true;
RobMeades 0:7ccf0e7e8a83 603 const char *buf = (const char *) data;
RobMeades 0:7ccf0e7e8a83 604 nsapi_size_t blk = MAX_WRITE_SIZE;
RobMeades 0:7ccf0e7e8a83 605 nsapi_size_t count = size;
RobMeades 0:7ccf0e7e8a83 606 SockCtrl *socket = (SockCtrl *) handle;
RobMeades 0:7ccf0e7e8a83 607
RobMeades 0:7ccf0e7e8a83 608 tr_debug("socket_sendto(0x%8x, %s(:%d), 0x%08x, %d)", (unsigned int) handle,
RobMeades 0:7ccf0e7e8a83 609 address.get_ip_address(), address.get_port(), (unsigned int) data, size);
RobMeades 0:7ccf0e7e8a83 610
RobMeades 0:7ccf0e7e8a83 611 MBED_ASSERT (check_socket(socket));
RobMeades 0:7ccf0e7e8a83 612
RobMeades 0:7ccf0e7e8a83 613 if (size > MAX_WRITE_SIZE) {
RobMeades 0:7ccf0e7e8a83 614 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 615 }
RobMeades 0:7ccf0e7e8a83 616
RobMeades 0:7ccf0e7e8a83 617 while ((count > 0) && success) {
RobMeades 0:7ccf0e7e8a83 618 if (count < blk) {
RobMeades 0:7ccf0e7e8a83 619 blk = count;
RobMeades 0:7ccf0e7e8a83 620 }
RobMeades 0:7ccf0e7e8a83 621 LOCK();
RobMeades 0:7ccf0e7e8a83 622
RobMeades 0:7ccf0e7e8a83 623 if (_at->send("AT+USOST=%d,\"%s\",%d,%d", socket->modem_handle,
RobMeades 0:7ccf0e7e8a83 624 address.get_ip_address(), address.get_port(), blk) &&
RobMeades 0:7ccf0e7e8a83 625 _at->recv("@")) {
RobMeades 0:7ccf0e7e8a83 626 wait_ms(50);
RobMeades 0:7ccf0e7e8a83 627 if ((_at->write(buf, blk) >= (int) blk) &&
RobMeades 0:7ccf0e7e8a83 628 _at->recv("OK")) {
RobMeades 0:7ccf0e7e8a83 629 } else {
RobMeades 0:7ccf0e7e8a83 630 success = false;
RobMeades 0:7ccf0e7e8a83 631 }
RobMeades 0:7ccf0e7e8a83 632 } else {
RobMeades 0:7ccf0e7e8a83 633 success = false;
RobMeades 0:7ccf0e7e8a83 634 }
RobMeades 0:7ccf0e7e8a83 635
RobMeades 0:7ccf0e7e8a83 636 UNLOCK();
RobMeades 0:7ccf0e7e8a83 637 buf += blk;
RobMeades 0:7ccf0e7e8a83 638 count -= blk;
RobMeades 0:7ccf0e7e8a83 639 }
RobMeades 0:7ccf0e7e8a83 640
RobMeades 0:7ccf0e7e8a83 641 if (success) {
RobMeades 0:7ccf0e7e8a83 642 nsapi_error_size = size - count;
RobMeades 0:7ccf0e7e8a83 643 if (_debug_trace_on) {
RobMeades 0:7ccf0e7e8a83 644 tr_debug("socket_sendto: %d \"%*.*s\"", size, size, size, (char *) data);
RobMeades 0:7ccf0e7e8a83 645 }
RobMeades 0:7ccf0e7e8a83 646 }
RobMeades 0:7ccf0e7e8a83 647
RobMeades 0:7ccf0e7e8a83 648 return nsapi_error_size;
RobMeades 0:7ccf0e7e8a83 649 }
RobMeades 0:7ccf0e7e8a83 650
RobMeades 0:7ccf0e7e8a83 651 // Receive from a socket, TCP style.
RobMeades 0:7ccf0e7e8a83 652 nsapi_size_or_error_t UbloxATCellularInterface::socket_recv(nsapi_socket_t handle,
RobMeades 0:7ccf0e7e8a83 653 void *data,
RobMeades 0:7ccf0e7e8a83 654 nsapi_size_t size)
RobMeades 0:7ccf0e7e8a83 655 {
RobMeades 0:7ccf0e7e8a83 656 nsapi_size_or_error_t nsapi_error_size = NSAPI_ERROR_DEVICE_ERROR;
RobMeades 0:7ccf0e7e8a83 657 bool success = true;
RobMeades 0:7ccf0e7e8a83 658 char *buf = (char *) data;
RobMeades 0:7ccf0e7e8a83 659 nsapi_size_t read_blk;
RobMeades 0:7ccf0e7e8a83 660 nsapi_size_t count = 0;
RobMeades 0:7ccf0e7e8a83 661 unsigned int usord_sz;
RobMeades 0:7ccf0e7e8a83 662 int read_sz;
RobMeades 0:7ccf0e7e8a83 663 Timer timer;
RobMeades 0:7ccf0e7e8a83 664 SockCtrl *socket = (SockCtrl *) handle;
RobMeades 0:7ccf0e7e8a83 665 int at_timeout;
RobMeades 0:7ccf0e7e8a83 666
RobMeades 0:7ccf0e7e8a83 667 tr_debug("socket_recv(0x%08x, 0x%08x, %d)",
RobMeades 0:7ccf0e7e8a83 668 (unsigned int) handle, (unsigned int) data, size);
RobMeades 0:7ccf0e7e8a83 669
RobMeades 0:7ccf0e7e8a83 670 MBED_ASSERT (check_socket(socket));
RobMeades 0:7ccf0e7e8a83 671
RobMeades 0:7ccf0e7e8a83 672 timer.start();
RobMeades 0:7ccf0e7e8a83 673
RobMeades 0:7ccf0e7e8a83 674 while (success && (size > 0)) {
RobMeades 0:7ccf0e7e8a83 675 LOCK();
RobMeades 0:7ccf0e7e8a83 676 at_timeout = _at_timeout;
RobMeades 0:7ccf0e7e8a83 677 at_set_timeout(1000);
RobMeades 0:7ccf0e7e8a83 678
RobMeades 0:7ccf0e7e8a83 679 read_blk = MAX_READ_SIZE;
RobMeades 0:7ccf0e7e8a83 680 if (read_blk > size) {
RobMeades 0:7ccf0e7e8a83 681 read_blk = size;
RobMeades 0:7ccf0e7e8a83 682 }
RobMeades 0:7ccf0e7e8a83 683 if (socket->pending > 0) {
RobMeades 0:7ccf0e7e8a83 684 tr_debug("Socket 0x%08x: modem handle %d has %d byte(s) pending",
RobMeades 0:7ccf0e7e8a83 685 (unsigned int) socket, socket->modem_handle, socket->pending);
RobMeades 0:7ccf0e7e8a83 686 _at->debug_on(false); // ABSOLUTELY no time for debug here if you want to
RobMeades 0:7ccf0e7e8a83 687 // be able to read packets of any size without
RobMeades 0:7ccf0e7e8a83 688 // losing characters in UARTSerial
RobMeades 0:7ccf0e7e8a83 689 if (_at->send("AT+USORD=%d,%d", socket->modem_handle, read_blk) &&
RobMeades 0:7ccf0e7e8a83 690 _at->recv("+USORD: %*d,%d,\"", &usord_sz)) {
RobMeades 0:7ccf0e7e8a83 691 socket->pending -= usord_sz; // Must use what +USORD returns here as it
RobMeades 0:7ccf0e7e8a83 692 // may be less than we asked for
RobMeades 0:7ccf0e7e8a83 693 // Note: insert no debug between _at->recv() and _at->read(), no time...
RobMeades 0:7ccf0e7e8a83 694 if (usord_sz > size) {
RobMeades 0:7ccf0e7e8a83 695 usord_sz = size;
RobMeades 0:7ccf0e7e8a83 696 }
RobMeades 0:7ccf0e7e8a83 697 read_sz = _at->read(buf, usord_sz);
RobMeades 0:7ccf0e7e8a83 698 if (read_sz > 0) {
RobMeades 0:7ccf0e7e8a83 699 tr_debug("...read %d byte(s) from modem handle %d...", read_sz,
RobMeades 0:7ccf0e7e8a83 700 socket->modem_handle);
RobMeades 0:7ccf0e7e8a83 701 if (_debug_trace_on) {
RobMeades 0:7ccf0e7e8a83 702 tr_debug("Read returned %d, |%*.*s|", read_sz, read_sz, read_sz, buf);
RobMeades 0:7ccf0e7e8a83 703 }
RobMeades 0:7ccf0e7e8a83 704 count += read_sz;
RobMeades 0:7ccf0e7e8a83 705 buf += read_sz;
RobMeades 0:7ccf0e7e8a83 706 size -= read_sz;
RobMeades 0:7ccf0e7e8a83 707 } else {
RobMeades 0:7ccf0e7e8a83 708 // read() should not fail
RobMeades 0:7ccf0e7e8a83 709 success = false;
RobMeades 0:7ccf0e7e8a83 710 }
RobMeades 0:7ccf0e7e8a83 711 tr_debug("Socket 0x%08x: modem handle %d now has only %d byte(s) pending",
RobMeades 0:7ccf0e7e8a83 712 (unsigned int) socket, socket->modem_handle, socket->pending);
RobMeades 0:7ccf0e7e8a83 713 // Wait for the "OK" before continuing
RobMeades 0:7ccf0e7e8a83 714 _at->recv("OK");
RobMeades 0:7ccf0e7e8a83 715 } else {
RobMeades 0:7ccf0e7e8a83 716 // Should never fail to do _at->send()/_at->recv()
RobMeades 0:7ccf0e7e8a83 717 success = false;
RobMeades 0:7ccf0e7e8a83 718 }
RobMeades 0:7ccf0e7e8a83 719 _at->debug_on(_debug_trace_on);
RobMeades 0:7ccf0e7e8a83 720 } else if (timer.read_ms() < SOCKET_TIMEOUT) {
RobMeades 0:7ccf0e7e8a83 721 // Wait for URCs
RobMeades 0:7ccf0e7e8a83 722 _at->recv(UNNATURAL_STRING);
RobMeades 0:7ccf0e7e8a83 723 } else {
RobMeades 0:7ccf0e7e8a83 724 if (count == 0) {
RobMeades 0:7ccf0e7e8a83 725 // Timeout with nothing received
RobMeades 0:7ccf0e7e8a83 726 nsapi_error_size = NSAPI_ERROR_WOULD_BLOCK;
RobMeades 0:7ccf0e7e8a83 727 success = false;
RobMeades 0:7ccf0e7e8a83 728 }
RobMeades 0:7ccf0e7e8a83 729 size = 0; // This simply to cause an exit
RobMeades 0:7ccf0e7e8a83 730 }
RobMeades 0:7ccf0e7e8a83 731
RobMeades 0:7ccf0e7e8a83 732 at_set_timeout(at_timeout);
RobMeades 0:7ccf0e7e8a83 733 UNLOCK();
RobMeades 0:7ccf0e7e8a83 734 }
RobMeades 0:7ccf0e7e8a83 735 timer.stop();
RobMeades 0:7ccf0e7e8a83 736
RobMeades 0:7ccf0e7e8a83 737 if (success) {
RobMeades 0:7ccf0e7e8a83 738 nsapi_error_size = count;
RobMeades 0:7ccf0e7e8a83 739 }
RobMeades 0:7ccf0e7e8a83 740
RobMeades 0:7ccf0e7e8a83 741 if (_debug_trace_on) {
RobMeades 0:7ccf0e7e8a83 742 tr_debug("socket_recv: %d \"%*.*s\"", count, count, count, buf - count);
RobMeades 0:7ccf0e7e8a83 743 } else {
RobMeades 0:7ccf0e7e8a83 744 tr_debug("socket_recv: received %d byte(s)", count);
RobMeades 0:7ccf0e7e8a83 745 }
RobMeades 0:7ccf0e7e8a83 746
RobMeades 0:7ccf0e7e8a83 747 return nsapi_error_size;
RobMeades 0:7ccf0e7e8a83 748 }
RobMeades 0:7ccf0e7e8a83 749
RobMeades 0:7ccf0e7e8a83 750 // Receive a packet over a UDP socket.
RobMeades 0:7ccf0e7e8a83 751 nsapi_size_or_error_t UbloxATCellularInterface::socket_recvfrom(nsapi_socket_t handle,
RobMeades 0:7ccf0e7e8a83 752 SocketAddress *address,
RobMeades 0:7ccf0e7e8a83 753 void *data,
RobMeades 0:7ccf0e7e8a83 754 nsapi_size_t size)
RobMeades 0:7ccf0e7e8a83 755 {
RobMeades 0:7ccf0e7e8a83 756 nsapi_size_or_error_t nsapi_error_size = NSAPI_ERROR_DEVICE_ERROR;
RobMeades 0:7ccf0e7e8a83 757 bool success = true;
RobMeades 0:7ccf0e7e8a83 758 char *buf = (char *) data;
RobMeades 0:7ccf0e7e8a83 759 nsapi_size_t read_blk;
RobMeades 0:7ccf0e7e8a83 760 nsapi_size_t count = 0;
RobMeades 0:7ccf0e7e8a83 761 char ipAddress[NSAPI_IP_SIZE];
RobMeades 0:7ccf0e7e8a83 762 int port;
RobMeades 0:7ccf0e7e8a83 763 unsigned int usorf_sz;
RobMeades 0:7ccf0e7e8a83 764 int read_sz;
RobMeades 0:7ccf0e7e8a83 765 Timer timer;
RobMeades 0:7ccf0e7e8a83 766 SockCtrl *socket = (SockCtrl *) handle;
RobMeades 0:7ccf0e7e8a83 767 int at_timeout;
RobMeades 0:7ccf0e7e8a83 768
RobMeades 0:7ccf0e7e8a83 769 tr_debug("socket_recvfrom(0x%08x, 0x%08x, %d)",
RobMeades 0:7ccf0e7e8a83 770 (unsigned int) handle, (unsigned int) data, size);
RobMeades 0:7ccf0e7e8a83 771
RobMeades 0:7ccf0e7e8a83 772 MBED_ASSERT (check_socket(socket));
RobMeades 0:7ccf0e7e8a83 773
RobMeades 0:7ccf0e7e8a83 774 timer.start();
RobMeades 0:7ccf0e7e8a83 775
RobMeades 0:7ccf0e7e8a83 776 while (success && (size > 0)) {
RobMeades 0:7ccf0e7e8a83 777 LOCK();
RobMeades 0:7ccf0e7e8a83 778 at_timeout = _at_timeout;
RobMeades 0:7ccf0e7e8a83 779 at_set_timeout(1000);
RobMeades 0:7ccf0e7e8a83 780
RobMeades 0:7ccf0e7e8a83 781 read_blk = MAX_READ_SIZE;
RobMeades 0:7ccf0e7e8a83 782 if (read_blk > size) {
RobMeades 0:7ccf0e7e8a83 783 read_blk = size;
RobMeades 0:7ccf0e7e8a83 784 }
RobMeades 0:7ccf0e7e8a83 785 if (socket->pending > 0) {
RobMeades 0:7ccf0e7e8a83 786 tr_debug("Socket 0x%08x: modem handle %d has %d byte(s) pending",
RobMeades 0:7ccf0e7e8a83 787 (unsigned int) socket, socket->modem_handle, socket->pending);
RobMeades 0:7ccf0e7e8a83 788 memset (ipAddress, 0, sizeof (ipAddress)); // Ensure terminator
RobMeades 0:7ccf0e7e8a83 789
RobMeades 0:7ccf0e7e8a83 790 // Note: the maximum length of UDP packet we can receive comes from
RobMeades 0:7ccf0e7e8a83 791 // fitting all of the following into one buffer:
RobMeades 0:7ccf0e7e8a83 792 //
RobMeades 0:7ccf0e7e8a83 793 // +USORF: xx,"max.len.ip.address.ipv4.or.ipv6",yyyyy,wwww,"the_data"\r\n
RobMeades 0:7ccf0e7e8a83 794 //
RobMeades 0:7ccf0e7e8a83 795 // where xx is the handle, max.len.ip.address.ipv4.or.ipv6 is NSAPI_IP_SIZE,
RobMeades 0:7ccf0e7e8a83 796 // yyyyy is the port number (max 65536), wwww is the length of the data and
RobMeades 0:7ccf0e7e8a83 797 // the_data is binary data. I make that 29 + 48 + len(the_data),
RobMeades 0:7ccf0e7e8a83 798 // so the overhead is 77 bytes.
RobMeades 0:7ccf0e7e8a83 799
RobMeades 0:7ccf0e7e8a83 800 _at->debug_on(false); // ABSOLUTELY no time for debug here if you want to
RobMeades 0:7ccf0e7e8a83 801 // be able to read packets of any size without
RobMeades 0:7ccf0e7e8a83 802 // losing characters in UARTSerial
RobMeades 0:7ccf0e7e8a83 803 if (_at->send("AT+USORF=%d,%d", socket->modem_handle, read_blk) &&
RobMeades 0:7ccf0e7e8a83 804 _at->recv("+USORF: %*d,\"%" u_stringify(NSAPI_IP_SIZE) "[^\"]\",%d,%d,\"",
RobMeades 0:7ccf0e7e8a83 805 ipAddress, &port, &usorf_sz)) {
RobMeades 0:7ccf0e7e8a83 806 socket->pending -= usorf_sz; // Must use what +USORF returns here as it
RobMeades 0:7ccf0e7e8a83 807 // may be less than we asked for
RobMeades 0:7ccf0e7e8a83 808 // Note: insert no debug between _at->recv() and _at->read(), no time...
RobMeades 0:7ccf0e7e8a83 809 if (usorf_sz > size) {
RobMeades 0:7ccf0e7e8a83 810 usorf_sz = size;
RobMeades 0:7ccf0e7e8a83 811 }
RobMeades 0:7ccf0e7e8a83 812 read_sz = _at->read(buf, usorf_sz);
RobMeades 0:7ccf0e7e8a83 813 if (read_sz > 0) {
RobMeades 0:7ccf0e7e8a83 814 address->set_ip_address(ipAddress);
RobMeades 0:7ccf0e7e8a83 815 address->set_port(port);
RobMeades 0:7ccf0e7e8a83 816 tr_debug("...read %d byte(s) from modem handle %d...", read_sz,
RobMeades 0:7ccf0e7e8a83 817 socket->modem_handle);
RobMeades 0:7ccf0e7e8a83 818 if (_debug_trace_on) {
RobMeades 0:7ccf0e7e8a83 819 tr_debug("Read returned %d, |%*.*s|", read_sz, read_sz, read_sz, buf);
RobMeades 0:7ccf0e7e8a83 820 }
RobMeades 0:7ccf0e7e8a83 821 count += read_sz;
RobMeades 0:7ccf0e7e8a83 822 buf += read_sz;
RobMeades 0:7ccf0e7e8a83 823 size -= read_sz;
RobMeades 0:7ccf0e7e8a83 824 if ((usorf_sz < read_blk) || (usorf_sz == MAX_READ_SIZE)) {
RobMeades 0:7ccf0e7e8a83 825 size = 0; // If we've received less than we asked for, or
RobMeades 0:7ccf0e7e8a83 826 // the max size, then a whole UDP packet has arrived and
RobMeades 0:7ccf0e7e8a83 827 // this means DONE.
RobMeades 0:7ccf0e7e8a83 828 }
RobMeades 0:7ccf0e7e8a83 829 } else {
RobMeades 0:7ccf0e7e8a83 830 // read() should not fail
RobMeades 0:7ccf0e7e8a83 831 success = false;
RobMeades 0:7ccf0e7e8a83 832 }
RobMeades 0:7ccf0e7e8a83 833 tr_debug("Socket 0x%08x: modem handle %d now has only %d byte(s) pending",
RobMeades 0:7ccf0e7e8a83 834 (unsigned int) socket, socket->modem_handle, socket->pending);
RobMeades 0:7ccf0e7e8a83 835 // Wait for the "OK" before continuing
RobMeades 0:7ccf0e7e8a83 836 _at->recv("OK");
RobMeades 0:7ccf0e7e8a83 837 } else {
RobMeades 0:7ccf0e7e8a83 838 // Should never fail to do _at->send()/_at->recv()
RobMeades 0:7ccf0e7e8a83 839 success = false;
RobMeades 0:7ccf0e7e8a83 840 }
RobMeades 0:7ccf0e7e8a83 841 _at->debug_on(_debug_trace_on);
RobMeades 0:7ccf0e7e8a83 842 } else if (timer.read_ms() < SOCKET_TIMEOUT) {
RobMeades 0:7ccf0e7e8a83 843 // Wait for URCs
RobMeades 0:7ccf0e7e8a83 844 _at->recv(UNNATURAL_STRING);
RobMeades 0:7ccf0e7e8a83 845 } else {
RobMeades 0:7ccf0e7e8a83 846 if (count == 0) {
RobMeades 0:7ccf0e7e8a83 847 // Timeout with nothing received
RobMeades 0:7ccf0e7e8a83 848 nsapi_error_size = NSAPI_ERROR_WOULD_BLOCK;
RobMeades 0:7ccf0e7e8a83 849 success = false;
RobMeades 0:7ccf0e7e8a83 850 }
RobMeades 0:7ccf0e7e8a83 851 size = 0; // This simply to cause an exit
RobMeades 0:7ccf0e7e8a83 852 }
RobMeades 0:7ccf0e7e8a83 853
RobMeades 0:7ccf0e7e8a83 854 at_set_timeout(at_timeout);
RobMeades 0:7ccf0e7e8a83 855 UNLOCK();
RobMeades 0:7ccf0e7e8a83 856 }
RobMeades 0:7ccf0e7e8a83 857 timer.stop();
RobMeades 0:7ccf0e7e8a83 858
RobMeades 0:7ccf0e7e8a83 859 if (success) {
RobMeades 0:7ccf0e7e8a83 860 nsapi_error_size = count;
RobMeades 0:7ccf0e7e8a83 861 }
RobMeades 0:7ccf0e7e8a83 862
RobMeades 0:7ccf0e7e8a83 863 if (_debug_trace_on) {
RobMeades 0:7ccf0e7e8a83 864 tr_debug("socket_recvfrom: %d \"%*.*s\"", count, count, count, buf - count);
RobMeades 0:7ccf0e7e8a83 865 } else {
RobMeades 0:7ccf0e7e8a83 866 tr_debug("socket_recvfrom: received %d byte(s)", count);
RobMeades 0:7ccf0e7e8a83 867 }
RobMeades 0:7ccf0e7e8a83 868
RobMeades 0:7ccf0e7e8a83 869 return nsapi_error_size;
RobMeades 0:7ccf0e7e8a83 870 }
RobMeades 0:7ccf0e7e8a83 871
RobMeades 0:7ccf0e7e8a83 872 // Attach an event callback to a socket, required for asynchronous
RobMeades 0:7ccf0e7e8a83 873 // data reception
RobMeades 0:7ccf0e7e8a83 874 void UbloxATCellularInterface::socket_attach(nsapi_socket_t handle,
RobMeades 0:7ccf0e7e8a83 875 void (*callback)(void *),
RobMeades 0:7ccf0e7e8a83 876 void *data)
RobMeades 0:7ccf0e7e8a83 877 {
RobMeades 0:7ccf0e7e8a83 878 SockCtrl *socket = (SockCtrl *) handle;
RobMeades 0:7ccf0e7e8a83 879
RobMeades 0:7ccf0e7e8a83 880 MBED_ASSERT (check_socket(socket));
RobMeades 0:7ccf0e7e8a83 881
RobMeades 0:7ccf0e7e8a83 882 socket->callback = callback;
RobMeades 0:7ccf0e7e8a83 883 socket->data = data;
RobMeades 0:7ccf0e7e8a83 884 }
RobMeades 0:7ccf0e7e8a83 885
RobMeades 0:7ccf0e7e8a83 886 // Unsupported TCP server functions.
RobMeades 0:7ccf0e7e8a83 887 nsapi_error_t UbloxATCellularInterface::socket_listen(nsapi_socket_t handle,
RobMeades 0:7ccf0e7e8a83 888 int backlog)
RobMeades 0:7ccf0e7e8a83 889 {
RobMeades 0:7ccf0e7e8a83 890 return NSAPI_ERROR_UNSUPPORTED;
RobMeades 0:7ccf0e7e8a83 891 }
RobMeades 0:7ccf0e7e8a83 892 nsapi_error_t UbloxATCellularInterface::socket_accept(nsapi_socket_t server,
RobMeades 0:7ccf0e7e8a83 893 nsapi_socket_t *handle,
RobMeades 0:7ccf0e7e8a83 894 SocketAddress *address)
RobMeades 0:7ccf0e7e8a83 895 {
RobMeades 0:7ccf0e7e8a83 896 return NSAPI_ERROR_UNSUPPORTED;
RobMeades 0:7ccf0e7e8a83 897 }
RobMeades 0:7ccf0e7e8a83 898
RobMeades 0:7ccf0e7e8a83 899 // Unsupported option functions.
RobMeades 0:7ccf0e7e8a83 900 nsapi_error_t UbloxATCellularInterface::setsockopt(nsapi_socket_t handle,
RobMeades 0:7ccf0e7e8a83 901 int level, int optname,
RobMeades 0:7ccf0e7e8a83 902 const void *optval,
RobMeades 0:7ccf0e7e8a83 903 unsigned optlen)
RobMeades 0:7ccf0e7e8a83 904 {
RobMeades 0:7ccf0e7e8a83 905 return NSAPI_ERROR_UNSUPPORTED;
RobMeades 0:7ccf0e7e8a83 906 }
RobMeades 0:7ccf0e7e8a83 907 nsapi_error_t UbloxATCellularInterface::getsockopt(nsapi_socket_t handle,
RobMeades 0:7ccf0e7e8a83 908 int level, int optname,
RobMeades 0:7ccf0e7e8a83 909 void *optval,
RobMeades 0:7ccf0e7e8a83 910 unsigned *optlen)
RobMeades 0:7ccf0e7e8a83 911 {
RobMeades 0:7ccf0e7e8a83 912 return NSAPI_ERROR_UNSUPPORTED;
RobMeades 0:7ccf0e7e8a83 913 }
RobMeades 0:7ccf0e7e8a83 914
RobMeades 0:7ccf0e7e8a83 915 /**********************************************************************
RobMeades 0:7ccf0e7e8a83 916 * PUBLIC METHODS
RobMeades 0:7ccf0e7e8a83 917 **********************************************************************/
RobMeades 0:7ccf0e7e8a83 918
RobMeades 0:7ccf0e7e8a83 919 // Constructor.
RobMeades 0:7ccf0e7e8a83 920 UbloxATCellularInterface::UbloxATCellularInterface(PinName tx,
RobMeades 0:7ccf0e7e8a83 921 PinName rx,
RobMeades 0:7ccf0e7e8a83 922 int baud,
RobMeades 0:7ccf0e7e8a83 923 bool debug_on)
RobMeades 0:7ccf0e7e8a83 924 {
RobMeades 0:7ccf0e7e8a83 925 _sim_pin_check_change_pending = false;
RobMeades 0:7ccf0e7e8a83 926 _sim_pin_check_change_pending_enabled_value = false;
RobMeades 0:7ccf0e7e8a83 927 _sim_pin_change_pending = false;
RobMeades 0:7ccf0e7e8a83 928 _sim_pin_change_pending_new_pin_value = NULL;
RobMeades 0:7ccf0e7e8a83 929 _apn = NULL;
RobMeades 0:7ccf0e7e8a83 930 _uname = NULL;
RobMeades 0:7ccf0e7e8a83 931 _pwd = NULL;
RobMeades 0:7ccf0e7e8a83 932 _connection_status_cb = NULL;
RobMeades 0:7ccf0e7e8a83 933
RobMeades 0:7ccf0e7e8a83 934 // Initialise sockets storage
RobMeades 0:7ccf0e7e8a83 935 memset(_sockets, 0, sizeof(_sockets));
RobMeades 0:7ccf0e7e8a83 936 for (unsigned int socket = 0; socket < sizeof(_sockets) / sizeof(_sockets[0]); socket++) {
RobMeades 0:7ccf0e7e8a83 937 _sockets[socket].modem_handle = SOCKET_UNUSED;
RobMeades 0:7ccf0e7e8a83 938 _sockets[socket].callback = NULL;
RobMeades 0:7ccf0e7e8a83 939 _sockets[socket].data = NULL;
RobMeades 0:7ccf0e7e8a83 940 }
RobMeades 0:7ccf0e7e8a83 941
RobMeades 0:7ccf0e7e8a83 942 // The authentication to use
RobMeades 0:7ccf0e7e8a83 943 _auth = NSAPI_SECURITY_UNKNOWN;
RobMeades 0:7ccf0e7e8a83 944
RobMeades 0:7ccf0e7e8a83 945 // Nullify the temporary IP address storage
RobMeades 0:7ccf0e7e8a83 946 _ip = NULL;
RobMeades 0:7ccf0e7e8a83 947
RobMeades 0:7ccf0e7e8a83 948 // Initialise the base class, which starts the AT parser
RobMeades 0:7ccf0e7e8a83 949 baseClassInit(tx, rx, baud, debug_on);
RobMeades 0:7ccf0e7e8a83 950
RobMeades 0:7ccf0e7e8a83 951 // Start the event handler thread for Rx data
RobMeades 0:7ccf0e7e8a83 952 event_thread.start(callback(this, &UbloxATCellularInterface::handle_event));
RobMeades 0:7ccf0e7e8a83 953
RobMeades 0:7ccf0e7e8a83 954 // URC handlers for sockets
RobMeades 0:7ccf0e7e8a83 955 _at->oob("+UUSORD", callback(this, &UbloxATCellularInterface::UUSORD_URC));
RobMeades 0:7ccf0e7e8a83 956 _at->oob("+UUSORF", callback(this, &UbloxATCellularInterface::UUSORF_URC));
RobMeades 0:7ccf0e7e8a83 957 _at->oob("+UUSOCL", callback(this, &UbloxATCellularInterface::UUSOCL_URC));
RobMeades 0:7ccf0e7e8a83 958 _at->oob("+UUPSDD", callback(this, &UbloxATCellularInterface::UUPSDD_URC));
RobMeades 0:7ccf0e7e8a83 959 }
RobMeades 0:7ccf0e7e8a83 960
RobMeades 0:7ccf0e7e8a83 961 // Destructor.
RobMeades 0:7ccf0e7e8a83 962 UbloxATCellularInterface::~UbloxATCellularInterface()
RobMeades 0:7ccf0e7e8a83 963 {
RobMeades 0:7ccf0e7e8a83 964 // Free _ip if it was ever allocated
RobMeades 0:7ccf0e7e8a83 965 free(_ip);
RobMeades 0:7ccf0e7e8a83 966 }
RobMeades 0:7ccf0e7e8a83 967
RobMeades 0:7ccf0e7e8a83 968 // Set the authentication scheme.
RobMeades 0:7ccf0e7e8a83 969 void UbloxATCellularInterface::set_authentication(nsapi_security_t auth)
RobMeades 0:7ccf0e7e8a83 970 {
RobMeades 0:7ccf0e7e8a83 971 _auth = auth;
RobMeades 0:7ccf0e7e8a83 972 }
RobMeades 0:7ccf0e7e8a83 973
RobMeades 0:7ccf0e7e8a83 974 // Set APN, user name and password.
RobMeades 0:7ccf0e7e8a83 975 void UbloxATCellularInterface::set_credentials(const char *apn,
RobMeades 0:7ccf0e7e8a83 976 const char *uname,
RobMeades 0:7ccf0e7e8a83 977 const char *pwd)
RobMeades 0:7ccf0e7e8a83 978 {
RobMeades 0:7ccf0e7e8a83 979 _apn = apn;
RobMeades 0:7ccf0e7e8a83 980 _uname = uname;
RobMeades 0:7ccf0e7e8a83 981 _pwd = pwd;
RobMeades 0:7ccf0e7e8a83 982 }
RobMeades 0:7ccf0e7e8a83 983
RobMeades 0:7ccf0e7e8a83 984 // Set PIN.
RobMeades 0:7ccf0e7e8a83 985 void UbloxATCellularInterface::set_sim_pin(const char *pin) {
RobMeades 0:7ccf0e7e8a83 986 set_pin(pin);
RobMeades 0:7ccf0e7e8a83 987 }
RobMeades 0:7ccf0e7e8a83 988
RobMeades 0:7ccf0e7e8a83 989 // Get the IP address of a host.
RobMeades 0:7ccf0e7e8a83 990 nsapi_error_t UbloxATCellularInterface::gethostbyname(const char *host,
RobMeades 0:7ccf0e7e8a83 991 SocketAddress *address,
RobMeades 0:7ccf0e7e8a83 992 nsapi_version_t version)
RobMeades 0:7ccf0e7e8a83 993 {
RobMeades 0:7ccf0e7e8a83 994 nsapi_error_t nsapi_error = NSAPI_ERROR_DEVICE_ERROR;
RobMeades 0:7ccf0e7e8a83 995 char ipAddress[NSAPI_IP_SIZE];
RobMeades 0:7ccf0e7e8a83 996
RobMeades 0:7ccf0e7e8a83 997 if (address->set_ip_address(host)) {
RobMeades 0:7ccf0e7e8a83 998 nsapi_error = NSAPI_ERROR_OK;
RobMeades 0:7ccf0e7e8a83 999 } else {
RobMeades 0:7ccf0e7e8a83 1000 LOCK();
RobMeades 0:7ccf0e7e8a83 1001 memset (ipAddress, 0, sizeof (ipAddress)); // Ensure terminator
RobMeades 0:7ccf0e7e8a83 1002 if (_at->send("AT+UDNSRN=0,\"%s\"", host) &&
RobMeades 0:7ccf0e7e8a83 1003 _at->recv("+UDNSRN: \"%" u_stringify(NSAPI_IP_SIZE) "[^\"]\"", ipAddress) &&
RobMeades 0:7ccf0e7e8a83 1004 _at->recv("OK")) {
RobMeades 0:7ccf0e7e8a83 1005 if (address->set_ip_address(ipAddress)) {
RobMeades 0:7ccf0e7e8a83 1006 nsapi_error = NSAPI_ERROR_OK;
RobMeades 0:7ccf0e7e8a83 1007 }
RobMeades 0:7ccf0e7e8a83 1008 }
RobMeades 0:7ccf0e7e8a83 1009 UNLOCK();
RobMeades 0:7ccf0e7e8a83 1010 }
RobMeades 0:7ccf0e7e8a83 1011
RobMeades 0:7ccf0e7e8a83 1012 return nsapi_error;
RobMeades 0:7ccf0e7e8a83 1013 }
RobMeades 0:7ccf0e7e8a83 1014
RobMeades 0:7ccf0e7e8a83 1015 // Make a cellular connection
RobMeades 0:7ccf0e7e8a83 1016 nsapi_error_t UbloxATCellularInterface::connect(const char *sim_pin,
RobMeades 0:7ccf0e7e8a83 1017 const char *apn,
RobMeades 0:7ccf0e7e8a83 1018 const char *uname,
RobMeades 0:7ccf0e7e8a83 1019 const char *pwd)
RobMeades 0:7ccf0e7e8a83 1020 {
RobMeades 0:7ccf0e7e8a83 1021 nsapi_error_t nsapi_error;
RobMeades 0:7ccf0e7e8a83 1022
RobMeades 0:7ccf0e7e8a83 1023 if (sim_pin != NULL) {
RobMeades 0:7ccf0e7e8a83 1024 _pin = sim_pin;
RobMeades 0:7ccf0e7e8a83 1025 }
RobMeades 0:7ccf0e7e8a83 1026
RobMeades 0:7ccf0e7e8a83 1027 if (apn != NULL) {
RobMeades 0:7ccf0e7e8a83 1028 _apn = apn;
RobMeades 0:7ccf0e7e8a83 1029 }
RobMeades 0:7ccf0e7e8a83 1030
RobMeades 0:7ccf0e7e8a83 1031 if ((uname != NULL) && (pwd != NULL)) {
RobMeades 0:7ccf0e7e8a83 1032 _uname = uname;
RobMeades 0:7ccf0e7e8a83 1033 _pwd = pwd;
RobMeades 0:7ccf0e7e8a83 1034 } else {
RobMeades 0:7ccf0e7e8a83 1035 _uname = NULL;
RobMeades 0:7ccf0e7e8a83 1036 _pwd = NULL;
RobMeades 0:7ccf0e7e8a83 1037 }
RobMeades 0:7ccf0e7e8a83 1038
RobMeades 0:7ccf0e7e8a83 1039 nsapi_error = connect();
RobMeades 0:7ccf0e7e8a83 1040
RobMeades 0:7ccf0e7e8a83 1041 return nsapi_error;
RobMeades 0:7ccf0e7e8a83 1042 }
RobMeades 0:7ccf0e7e8a83 1043
RobMeades 0:7ccf0e7e8a83 1044 // Make a cellular connection using the IP stack on board the cellular modem
RobMeades 0:7ccf0e7e8a83 1045 nsapi_error_t UbloxATCellularInterface::connect()
RobMeades 0:7ccf0e7e8a83 1046 {
RobMeades 0:7ccf0e7e8a83 1047 nsapi_error_t nsapi_error = NSAPI_ERROR_DEVICE_ERROR;
RobMeades 0:7ccf0e7e8a83 1048 bool registered = false;
RobMeades 0:7ccf0e7e8a83 1049
RobMeades 0:7ccf0e7e8a83 1050 // Set up modem and then register with the network
RobMeades 0:7ccf0e7e8a83 1051 if (init()) {
RobMeades 0:7ccf0e7e8a83 1052 nsapi_error = NSAPI_ERROR_NO_CONNECTION;
RobMeades 0:7ccf0e7e8a83 1053 // Perform any pending SIM actions
RobMeades 0:7ccf0e7e8a83 1054 if (_sim_pin_check_change_pending) {
RobMeades 0:7ccf0e7e8a83 1055 if (!sim_pin_check_enable(_sim_pin_check_change_pending_enabled_value)) {
RobMeades 0:7ccf0e7e8a83 1056 nsapi_error = NSAPI_ERROR_AUTH_FAILURE;
RobMeades 0:7ccf0e7e8a83 1057 }
RobMeades 0:7ccf0e7e8a83 1058 _sim_pin_check_change_pending = false;
RobMeades 0:7ccf0e7e8a83 1059 }
RobMeades 0:7ccf0e7e8a83 1060 if (_sim_pin_change_pending) {
RobMeades 0:7ccf0e7e8a83 1061 if (!change_sim_pin(_sim_pin_change_pending_new_pin_value)) {
RobMeades 0:7ccf0e7e8a83 1062 nsapi_error = NSAPI_ERROR_AUTH_FAILURE;
RobMeades 0:7ccf0e7e8a83 1063 }
RobMeades 0:7ccf0e7e8a83 1064 _sim_pin_change_pending = false;
RobMeades 0:7ccf0e7e8a83 1065 }
RobMeades 0:7ccf0e7e8a83 1066
RobMeades 0:7ccf0e7e8a83 1067 if (nsapi_error == NSAPI_ERROR_NO_CONNECTION) {
RobMeades 0:7ccf0e7e8a83 1068 for (int retries = 0; !registered && (retries < 3); retries++) {
RobMeades 0:7ccf0e7e8a83 1069 if (nwk_registration()) {
RobMeades 0:7ccf0e7e8a83 1070 registered = true;;
RobMeades 0:7ccf0e7e8a83 1071 }
RobMeades 0:7ccf0e7e8a83 1072 }
RobMeades 0:7ccf0e7e8a83 1073 }
RobMeades 0:7ccf0e7e8a83 1074 }
RobMeades 0:7ccf0e7e8a83 1075
RobMeades 0:7ccf0e7e8a83 1076 // Attempt to establish a connection
RobMeades 0:7ccf0e7e8a83 1077 if (registered && connect_modem_stack()) {
RobMeades 0:7ccf0e7e8a83 1078 nsapi_error = NSAPI_ERROR_OK;
RobMeades 0:7ccf0e7e8a83 1079 }
RobMeades 0:7ccf0e7e8a83 1080
RobMeades 0:7ccf0e7e8a83 1081 return nsapi_error;
RobMeades 0:7ccf0e7e8a83 1082 }
RobMeades 0:7ccf0e7e8a83 1083
RobMeades 0:7ccf0e7e8a83 1084 // User initiated disconnect.
RobMeades 0:7ccf0e7e8a83 1085 nsapi_error_t UbloxATCellularInterface::disconnect()
RobMeades 0:7ccf0e7e8a83 1086 {
RobMeades 0:7ccf0e7e8a83 1087 nsapi_error_t nsapi_error = NSAPI_ERROR_DEVICE_ERROR;
RobMeades 0:7ccf0e7e8a83 1088
RobMeades 0:7ccf0e7e8a83 1089 if (disconnect_modem_stack() && nwk_deregistration()) {
RobMeades 0:7ccf0e7e8a83 1090 nsapi_error = NSAPI_ERROR_OK;
RobMeades 0:7ccf0e7e8a83 1091 }
RobMeades 0:7ccf0e7e8a83 1092
RobMeades 0:7ccf0e7e8a83 1093 return nsapi_error;
RobMeades 0:7ccf0e7e8a83 1094 }
RobMeades 0:7ccf0e7e8a83 1095
RobMeades 0:7ccf0e7e8a83 1096 // Enable or disable SIM PIN check lock.
RobMeades 0:7ccf0e7e8a83 1097 nsapi_error_t UbloxATCellularInterface::set_sim_pin_check(bool set,
RobMeades 0:7ccf0e7e8a83 1098 bool immediate,
RobMeades 0:7ccf0e7e8a83 1099 const char *sim_pin)
RobMeades 0:7ccf0e7e8a83 1100 {
RobMeades 0:7ccf0e7e8a83 1101 nsapi_error_t nsapi_error = NSAPI_ERROR_AUTH_FAILURE;
RobMeades 0:7ccf0e7e8a83 1102
RobMeades 0:7ccf0e7e8a83 1103 if (sim_pin != NULL) {
RobMeades 0:7ccf0e7e8a83 1104 _pin = sim_pin;
RobMeades 0:7ccf0e7e8a83 1105 }
RobMeades 0:7ccf0e7e8a83 1106
RobMeades 0:7ccf0e7e8a83 1107 if (immediate) {
RobMeades 0:7ccf0e7e8a83 1108 if (init()) {
RobMeades 0:7ccf0e7e8a83 1109 if (sim_pin_check_enable(set)) {
RobMeades 0:7ccf0e7e8a83 1110 nsapi_error = NSAPI_ERROR_OK;
RobMeades 0:7ccf0e7e8a83 1111 }
RobMeades 0:7ccf0e7e8a83 1112 } else {
RobMeades 0:7ccf0e7e8a83 1113 nsapi_error = NSAPI_ERROR_DEVICE_ERROR;
RobMeades 0:7ccf0e7e8a83 1114 }
RobMeades 0:7ccf0e7e8a83 1115 } else {
RobMeades 0:7ccf0e7e8a83 1116 nsapi_error = NSAPI_ERROR_OK;
RobMeades 0:7ccf0e7e8a83 1117 _sim_pin_check_change_pending = true;
RobMeades 0:7ccf0e7e8a83 1118 _sim_pin_check_change_pending_enabled_value = set;
RobMeades 0:7ccf0e7e8a83 1119 }
RobMeades 0:7ccf0e7e8a83 1120
RobMeades 0:7ccf0e7e8a83 1121 return nsapi_error;
RobMeades 0:7ccf0e7e8a83 1122 }
RobMeades 0:7ccf0e7e8a83 1123
RobMeades 0:7ccf0e7e8a83 1124 // Change the PIN code for the SIM card.
RobMeades 0:7ccf0e7e8a83 1125 nsapi_error_t UbloxATCellularInterface::set_new_sim_pin(const char *new_pin,
RobMeades 0:7ccf0e7e8a83 1126 bool immediate,
RobMeades 0:7ccf0e7e8a83 1127 const char *old_pin)
RobMeades 0:7ccf0e7e8a83 1128 {
RobMeades 0:7ccf0e7e8a83 1129 nsapi_error_t nsapi_error = NSAPI_ERROR_AUTH_FAILURE;
RobMeades 0:7ccf0e7e8a83 1130
RobMeades 0:7ccf0e7e8a83 1131 if (old_pin != NULL) {
RobMeades 0:7ccf0e7e8a83 1132 _pin = old_pin;
RobMeades 0:7ccf0e7e8a83 1133 }
RobMeades 0:7ccf0e7e8a83 1134
RobMeades 0:7ccf0e7e8a83 1135 if (immediate) {
RobMeades 0:7ccf0e7e8a83 1136 if (init()) {
RobMeades 0:7ccf0e7e8a83 1137 if (change_sim_pin(new_pin)) {
RobMeades 0:7ccf0e7e8a83 1138 nsapi_error = NSAPI_ERROR_OK;
RobMeades 0:7ccf0e7e8a83 1139 }
RobMeades 0:7ccf0e7e8a83 1140 } else {
RobMeades 0:7ccf0e7e8a83 1141 nsapi_error = NSAPI_ERROR_DEVICE_ERROR;
RobMeades 0:7ccf0e7e8a83 1142 }
RobMeades 0:7ccf0e7e8a83 1143 } else {
RobMeades 0:7ccf0e7e8a83 1144 nsapi_error = NSAPI_ERROR_OK;
RobMeades 0:7ccf0e7e8a83 1145 _sim_pin_change_pending = true;
RobMeades 0:7ccf0e7e8a83 1146 _sim_pin_change_pending_new_pin_value = new_pin;
RobMeades 0:7ccf0e7e8a83 1147 }
RobMeades 0:7ccf0e7e8a83 1148
RobMeades 0:7ccf0e7e8a83 1149 return nsapi_error;
RobMeades 0:7ccf0e7e8a83 1150 }
RobMeades 0:7ccf0e7e8a83 1151
RobMeades 0:7ccf0e7e8a83 1152 // Determine if the connection is up.
RobMeades 0:7ccf0e7e8a83 1153 bool UbloxATCellularInterface::is_connected()
RobMeades 0:7ccf0e7e8a83 1154 {
RobMeades 0:7ccf0e7e8a83 1155 return get_ip_address() != NULL;
RobMeades 0:7ccf0e7e8a83 1156 }
RobMeades 0:7ccf0e7e8a83 1157
RobMeades 0:7ccf0e7e8a83 1158 // Get the IP address of the on-board modem IP stack.
RobMeades 0:7ccf0e7e8a83 1159 const char * UbloxATCellularInterface::get_ip_address()
RobMeades 0:7ccf0e7e8a83 1160 {
RobMeades 0:7ccf0e7e8a83 1161 SocketAddress address;
RobMeades 0:7ccf0e7e8a83 1162 LOCK();
RobMeades 0:7ccf0e7e8a83 1163
RobMeades 0:7ccf0e7e8a83 1164 if (_ip == NULL) {
RobMeades 0:7ccf0e7e8a83 1165 // Temporary storage for an IP address string with terminator
RobMeades 0:7ccf0e7e8a83 1166 _ip = (char *) malloc(NSAPI_IP_SIZE);
RobMeades 0:7ccf0e7e8a83 1167 }
RobMeades 0:7ccf0e7e8a83 1168
RobMeades 0:7ccf0e7e8a83 1169 if (_ip != NULL) {
RobMeades 0:7ccf0e7e8a83 1170 memset(_ip, 0, NSAPI_IP_SIZE); // Ensure a terminator
RobMeades 0:7ccf0e7e8a83 1171 // +UPSND=<profile_id>,<param_tag>[,<dynamic_param_val>]
RobMeades 0:7ccf0e7e8a83 1172 // If we get back a quoted "w.x.y.z" then we have an IP address,
RobMeades 0:7ccf0e7e8a83 1173 // otherwise we don't.
RobMeades 0:7ccf0e7e8a83 1174 if (!_at->send("AT+UPSND=" PROFILE ",0") ||
RobMeades 0:7ccf0e7e8a83 1175 !_at->recv("+UPSND: " PROFILE ",0,\"%" u_stringify(NSAPI_IP_SIZE) "[^\"]\"", _ip) ||
RobMeades 0:7ccf0e7e8a83 1176 !_at->recv("OK") ||
RobMeades 0:7ccf0e7e8a83 1177 !address.set_ip_address(_ip) || // Return NULL if the address is not a valid one
RobMeades 0:7ccf0e7e8a83 1178 !address) { // Return null if the address is zero
RobMeades 0:7ccf0e7e8a83 1179 free (_ip);
RobMeades 0:7ccf0e7e8a83 1180 _ip = NULL;
RobMeades 0:7ccf0e7e8a83 1181 }
RobMeades 0:7ccf0e7e8a83 1182 }
RobMeades 0:7ccf0e7e8a83 1183
RobMeades 0:7ccf0e7e8a83 1184 UNLOCK();
RobMeades 0:7ccf0e7e8a83 1185 return _ip;
RobMeades 0:7ccf0e7e8a83 1186 }
RobMeades 0:7ccf0e7e8a83 1187
RobMeades 0:7ccf0e7e8a83 1188 // Get the local network mask.
RobMeades 0:7ccf0e7e8a83 1189 const char *UbloxATCellularInterface::get_netmask()
RobMeades 0:7ccf0e7e8a83 1190 {
RobMeades 0:7ccf0e7e8a83 1191 // Not implemented.
RobMeades 0:7ccf0e7e8a83 1192 return NULL;
RobMeades 0:7ccf0e7e8a83 1193 }
RobMeades 0:7ccf0e7e8a83 1194
RobMeades 0:7ccf0e7e8a83 1195 // Get the local gateways.
RobMeades 0:7ccf0e7e8a83 1196 const char *UbloxATCellularInterface::get_gateway()
RobMeades 0:7ccf0e7e8a83 1197 {
RobMeades 0:7ccf0e7e8a83 1198 return get_ip_address();
RobMeades 0:7ccf0e7e8a83 1199 }
RobMeades 0:7ccf0e7e8a83 1200
RobMeades 0:7ccf0e7e8a83 1201 // Callback in case the connection is lost.
RobMeades 0:7ccf0e7e8a83 1202 void UbloxATCellularInterface::connection_status_cb(Callback<void(nsapi_error_t)> cb)
RobMeades 0:7ccf0e7e8a83 1203 {
RobMeades 0:7ccf0e7e8a83 1204 _connection_status_cb = cb;
RobMeades 0:7ccf0e7e8a83 1205 }
RobMeades 0:7ccf0e7e8a83 1206
RobMeades 0:7ccf0e7e8a83 1207 // End of file
RobMeades 0:7ccf0e7e8a83 1208