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 Oct 30 14:48:14 2017 +0000
Revision:
10:ba18f4418ee8
Parent:
7:3b2ca10cc23a
Child:
11:cc41a8636f7e
Child:
12:ff6fac481487
Merge pull request from amq: usord and usorf can potentially return more data than originally requested, handle this situation if it occurs.

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
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 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.
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,
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
rob.meades@u-blox.com 7:3b2ca10cc23a 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 10:ba18f4418ee8 691 // Must use what +USORD returns here as it may be less or more than we asked for
RobMeades 10:ba18f4418ee8 692 if (usord_sz > socket->pending) {
RobMeades 10:ba18f4418ee8 693 socket->pending = 0;
RobMeades 10:ba18f4418ee8 694 } else {
RobMeades 10:ba18f4418ee8 695 socket->pending -= usord_sz;
RobMeades 10:ba18f4418ee8 696 }
RobMeades 0:7ccf0e7e8a83 697 // Note: insert no debug between _at->recv() and _at->read(), no time...
RobMeades 0:7ccf0e7e8a83 698 if (usord_sz > size) {
RobMeades 0:7ccf0e7e8a83 699 usord_sz = size;
RobMeades 0:7ccf0e7e8a83 700 }
RobMeades 0:7ccf0e7e8a83 701 read_sz = _at->read(buf, usord_sz);
RobMeades 0:7ccf0e7e8a83 702 if (read_sz > 0) {
RobMeades 0:7ccf0e7e8a83 703 tr_debug("...read %d byte(s) from modem handle %d...", read_sz,
RobMeades 0:7ccf0e7e8a83 704 socket->modem_handle);
RobMeades 0:7ccf0e7e8a83 705 if (_debug_trace_on) {
RobMeades 0:7ccf0e7e8a83 706 tr_debug("Read returned %d, |%*.*s|", read_sz, read_sz, read_sz, buf);
RobMeades 0:7ccf0e7e8a83 707 }
RobMeades 0:7ccf0e7e8a83 708 count += read_sz;
RobMeades 0:7ccf0e7e8a83 709 buf += read_sz;
RobMeades 0:7ccf0e7e8a83 710 size -= read_sz;
RobMeades 0:7ccf0e7e8a83 711 } else {
RobMeades 0:7ccf0e7e8a83 712 // read() should not fail
RobMeades 0:7ccf0e7e8a83 713 success = false;
RobMeades 0:7ccf0e7e8a83 714 }
RobMeades 0:7ccf0e7e8a83 715 tr_debug("Socket 0x%08x: modem handle %d now has only %d byte(s) pending",
RobMeades 0:7ccf0e7e8a83 716 (unsigned int) socket, socket->modem_handle, socket->pending);
RobMeades 0:7ccf0e7e8a83 717 // Wait for the "OK" before continuing
RobMeades 0:7ccf0e7e8a83 718 _at->recv("OK");
RobMeades 0:7ccf0e7e8a83 719 } else {
RobMeades 0:7ccf0e7e8a83 720 // Should never fail to do _at->send()/_at->recv()
RobMeades 0:7ccf0e7e8a83 721 success = false;
RobMeades 0:7ccf0e7e8a83 722 }
RobMeades 0:7ccf0e7e8a83 723 _at->debug_on(_debug_trace_on);
RobMeades 0:7ccf0e7e8a83 724 } else if (timer.read_ms() < SOCKET_TIMEOUT) {
RobMeades 0:7ccf0e7e8a83 725 // Wait for URCs
RobMeades 0:7ccf0e7e8a83 726 _at->recv(UNNATURAL_STRING);
RobMeades 0:7ccf0e7e8a83 727 } else {
RobMeades 0:7ccf0e7e8a83 728 if (count == 0) {
RobMeades 0:7ccf0e7e8a83 729 // Timeout with nothing received
RobMeades 0:7ccf0e7e8a83 730 nsapi_error_size = NSAPI_ERROR_WOULD_BLOCK;
RobMeades 0:7ccf0e7e8a83 731 success = false;
RobMeades 0:7ccf0e7e8a83 732 }
RobMeades 0:7ccf0e7e8a83 733 size = 0; // This simply to cause an exit
RobMeades 0:7ccf0e7e8a83 734 }
RobMeades 0:7ccf0e7e8a83 735
RobMeades 0:7ccf0e7e8a83 736 at_set_timeout(at_timeout);
RobMeades 0:7ccf0e7e8a83 737 UNLOCK();
RobMeades 0:7ccf0e7e8a83 738 }
RobMeades 0:7ccf0e7e8a83 739 timer.stop();
RobMeades 0:7ccf0e7e8a83 740
RobMeades 0:7ccf0e7e8a83 741 if (success) {
RobMeades 0:7ccf0e7e8a83 742 nsapi_error_size = count;
RobMeades 0:7ccf0e7e8a83 743 }
RobMeades 0:7ccf0e7e8a83 744
RobMeades 0:7ccf0e7e8a83 745 if (_debug_trace_on) {
RobMeades 0:7ccf0e7e8a83 746 tr_debug("socket_recv: %d \"%*.*s\"", count, count, count, buf - count);
RobMeades 0:7ccf0e7e8a83 747 } else {
RobMeades 0:7ccf0e7e8a83 748 tr_debug("socket_recv: received %d byte(s)", count);
RobMeades 0:7ccf0e7e8a83 749 }
RobMeades 0:7ccf0e7e8a83 750
RobMeades 0:7ccf0e7e8a83 751 return nsapi_error_size;
RobMeades 0:7ccf0e7e8a83 752 }
RobMeades 0:7ccf0e7e8a83 753
RobMeades 0:7ccf0e7e8a83 754 // Receive a packet over a UDP socket.
RobMeades 0:7ccf0e7e8a83 755 nsapi_size_or_error_t UbloxATCellularInterface::socket_recvfrom(nsapi_socket_t handle,
RobMeades 0:7ccf0e7e8a83 756 SocketAddress *address,
RobMeades 0:7ccf0e7e8a83 757 void *data,
RobMeades 0:7ccf0e7e8a83 758 nsapi_size_t size)
RobMeades 0:7ccf0e7e8a83 759 {
RobMeades 0:7ccf0e7e8a83 760 nsapi_size_or_error_t nsapi_error_size = NSAPI_ERROR_DEVICE_ERROR;
RobMeades 0:7ccf0e7e8a83 761 bool success = true;
RobMeades 0:7ccf0e7e8a83 762 char *buf = (char *) data;
RobMeades 0:7ccf0e7e8a83 763 nsapi_size_t read_blk;
RobMeades 0:7ccf0e7e8a83 764 nsapi_size_t count = 0;
RobMeades 0:7ccf0e7e8a83 765 char ipAddress[NSAPI_IP_SIZE];
RobMeades 0:7ccf0e7e8a83 766 int port;
RobMeades 0:7ccf0e7e8a83 767 unsigned int usorf_sz;
RobMeades 0:7ccf0e7e8a83 768 int read_sz;
RobMeades 0:7ccf0e7e8a83 769 Timer timer;
RobMeades 0:7ccf0e7e8a83 770 SockCtrl *socket = (SockCtrl *) handle;
RobMeades 0:7ccf0e7e8a83 771 int at_timeout;
RobMeades 0:7ccf0e7e8a83 772
RobMeades 0:7ccf0e7e8a83 773 tr_debug("socket_recvfrom(0x%08x, 0x%08x, %d)",
RobMeades 0:7ccf0e7e8a83 774 (unsigned int) handle, (unsigned int) data, size);
RobMeades 0:7ccf0e7e8a83 775
RobMeades 0:7ccf0e7e8a83 776 MBED_ASSERT (check_socket(socket));
RobMeades 0:7ccf0e7e8a83 777
RobMeades 0:7ccf0e7e8a83 778 timer.start();
RobMeades 0:7ccf0e7e8a83 779
RobMeades 0:7ccf0e7e8a83 780 while (success && (size > 0)) {
RobMeades 0:7ccf0e7e8a83 781 LOCK();
RobMeades 0:7ccf0e7e8a83 782 at_timeout = _at_timeout;
RobMeades 0:7ccf0e7e8a83 783 at_set_timeout(1000);
RobMeades 0:7ccf0e7e8a83 784
RobMeades 0:7ccf0e7e8a83 785 read_blk = MAX_READ_SIZE;
RobMeades 0:7ccf0e7e8a83 786 if (read_blk > size) {
RobMeades 0:7ccf0e7e8a83 787 read_blk = size;
RobMeades 0:7ccf0e7e8a83 788 }
RobMeades 0:7ccf0e7e8a83 789 if (socket->pending > 0) {
RobMeades 0:7ccf0e7e8a83 790 tr_debug("Socket 0x%08x: modem handle %d has %d byte(s) pending",
RobMeades 0:7ccf0e7e8a83 791 (unsigned int) socket, socket->modem_handle, socket->pending);
RobMeades 0:7ccf0e7e8a83 792 memset (ipAddress, 0, sizeof (ipAddress)); // Ensure terminator
RobMeades 0:7ccf0e7e8a83 793
RobMeades 0:7ccf0e7e8a83 794 // Note: the maximum length of UDP packet we can receive comes from
RobMeades 0:7ccf0e7e8a83 795 // fitting all of the following into one buffer:
RobMeades 0:7ccf0e7e8a83 796 //
RobMeades 0:7ccf0e7e8a83 797 // +USORF: xx,"max.len.ip.address.ipv4.or.ipv6",yyyyy,wwww,"the_data"\r\n
RobMeades 0:7ccf0e7e8a83 798 //
RobMeades 0:7ccf0e7e8a83 799 // where xx is the handle, max.len.ip.address.ipv4.or.ipv6 is NSAPI_IP_SIZE,
RobMeades 0:7ccf0e7e8a83 800 // yyyyy is the port number (max 65536), wwww is the length of the data and
RobMeades 0:7ccf0e7e8a83 801 // the_data is binary data. I make that 29 + 48 + len(the_data),
RobMeades 0:7ccf0e7e8a83 802 // so the overhead is 77 bytes.
RobMeades 0:7ccf0e7e8a83 803
RobMeades 0:7ccf0e7e8a83 804 _at->debug_on(false); // ABSOLUTELY no time for debug here if you want to
RobMeades 0:7ccf0e7e8a83 805 // be able to read packets of any size without
RobMeades 0:7ccf0e7e8a83 806 // losing characters in UARTSerial
RobMeades 0:7ccf0e7e8a83 807 if (_at->send("AT+USORF=%d,%d", socket->modem_handle, read_blk) &&
RobMeades 0:7ccf0e7e8a83 808 _at->recv("+USORF: %*d,\"%" u_stringify(NSAPI_IP_SIZE) "[^\"]\",%d,%d,\"",
RobMeades 0:7ccf0e7e8a83 809 ipAddress, &port, &usorf_sz)) {
RobMeades 10:ba18f4418ee8 810 // Must use what +USORF returns here as it may be less or more than we asked for
RobMeades 10:ba18f4418ee8 811 if (usorf_sz > socket->pending) {
RobMeades 10:ba18f4418ee8 812 socket->pending = 0;
RobMeades 10:ba18f4418ee8 813 } else {
RobMeades 10:ba18f4418ee8 814 socket->pending -= usorf_sz;
RobMeades 10:ba18f4418ee8 815 }
RobMeades 0:7ccf0e7e8a83 816 // Note: insert no debug between _at->recv() and _at->read(), no time...
RobMeades 0:7ccf0e7e8a83 817 if (usorf_sz > size) {
RobMeades 0:7ccf0e7e8a83 818 usorf_sz = size;
RobMeades 0:7ccf0e7e8a83 819 }
RobMeades 0:7ccf0e7e8a83 820 read_sz = _at->read(buf, usorf_sz);
RobMeades 0:7ccf0e7e8a83 821 if (read_sz > 0) {
RobMeades 0:7ccf0e7e8a83 822 address->set_ip_address(ipAddress);
RobMeades 0:7ccf0e7e8a83 823 address->set_port(port);
RobMeades 0:7ccf0e7e8a83 824 tr_debug("...read %d byte(s) from modem handle %d...", read_sz,
RobMeades 0:7ccf0e7e8a83 825 socket->modem_handle);
RobMeades 0:7ccf0e7e8a83 826 if (_debug_trace_on) {
RobMeades 0:7ccf0e7e8a83 827 tr_debug("Read returned %d, |%*.*s|", read_sz, read_sz, read_sz, buf);
RobMeades 0:7ccf0e7e8a83 828 }
RobMeades 0:7ccf0e7e8a83 829 count += read_sz;
RobMeades 0:7ccf0e7e8a83 830 buf += read_sz;
RobMeades 0:7ccf0e7e8a83 831 size -= read_sz;
RobMeades 0:7ccf0e7e8a83 832 if ((usorf_sz < read_blk) || (usorf_sz == MAX_READ_SIZE)) {
RobMeades 0:7ccf0e7e8a83 833 size = 0; // If we've received less than we asked for, or
RobMeades 0:7ccf0e7e8a83 834 // the max size, then a whole UDP packet has arrived and
RobMeades 0:7ccf0e7e8a83 835 // this means DONE.
RobMeades 0:7ccf0e7e8a83 836 }
RobMeades 0:7ccf0e7e8a83 837 } else {
RobMeades 0:7ccf0e7e8a83 838 // read() should not fail
RobMeades 0:7ccf0e7e8a83 839 success = false;
RobMeades 0:7ccf0e7e8a83 840 }
RobMeades 0:7ccf0e7e8a83 841 tr_debug("Socket 0x%08x: modem handle %d now has only %d byte(s) pending",
RobMeades 0:7ccf0e7e8a83 842 (unsigned int) socket, socket->modem_handle, socket->pending);
RobMeades 0:7ccf0e7e8a83 843 // Wait for the "OK" before continuing
RobMeades 0:7ccf0e7e8a83 844 _at->recv("OK");
RobMeades 0:7ccf0e7e8a83 845 } else {
RobMeades 0:7ccf0e7e8a83 846 // Should never fail to do _at->send()/_at->recv()
RobMeades 0:7ccf0e7e8a83 847 success = false;
RobMeades 0:7ccf0e7e8a83 848 }
RobMeades 0:7ccf0e7e8a83 849 _at->debug_on(_debug_trace_on);
RobMeades 0:7ccf0e7e8a83 850 } else if (timer.read_ms() < SOCKET_TIMEOUT) {
RobMeades 0:7ccf0e7e8a83 851 // Wait for URCs
RobMeades 0:7ccf0e7e8a83 852 _at->recv(UNNATURAL_STRING);
RobMeades 0:7ccf0e7e8a83 853 } else {
RobMeades 0:7ccf0e7e8a83 854 if (count == 0) {
RobMeades 0:7ccf0e7e8a83 855 // Timeout with nothing received
RobMeades 0:7ccf0e7e8a83 856 nsapi_error_size = NSAPI_ERROR_WOULD_BLOCK;
RobMeades 0:7ccf0e7e8a83 857 success = false;
RobMeades 0:7ccf0e7e8a83 858 }
RobMeades 0:7ccf0e7e8a83 859 size = 0; // This simply to cause an exit
RobMeades 0:7ccf0e7e8a83 860 }
RobMeades 0:7ccf0e7e8a83 861
RobMeades 0:7ccf0e7e8a83 862 at_set_timeout(at_timeout);
RobMeades 0:7ccf0e7e8a83 863 UNLOCK();
RobMeades 0:7ccf0e7e8a83 864 }
RobMeades 0:7ccf0e7e8a83 865 timer.stop();
RobMeades 0:7ccf0e7e8a83 866
RobMeades 0:7ccf0e7e8a83 867 if (success) {
RobMeades 0:7ccf0e7e8a83 868 nsapi_error_size = count;
RobMeades 0:7ccf0e7e8a83 869 }
RobMeades 0:7ccf0e7e8a83 870
RobMeades 0:7ccf0e7e8a83 871 if (_debug_trace_on) {
RobMeades 0:7ccf0e7e8a83 872 tr_debug("socket_recvfrom: %d \"%*.*s\"", count, count, count, buf - count);
RobMeades 0:7ccf0e7e8a83 873 } else {
RobMeades 0:7ccf0e7e8a83 874 tr_debug("socket_recvfrom: received %d byte(s)", count);
RobMeades 0:7ccf0e7e8a83 875 }
RobMeades 0:7ccf0e7e8a83 876
RobMeades 0:7ccf0e7e8a83 877 return nsapi_error_size;
RobMeades 0:7ccf0e7e8a83 878 }
RobMeades 0:7ccf0e7e8a83 879
RobMeades 0:7ccf0e7e8a83 880 // Attach an event callback to a socket, required for asynchronous
RobMeades 0:7ccf0e7e8a83 881 // data reception
RobMeades 0:7ccf0e7e8a83 882 void UbloxATCellularInterface::socket_attach(nsapi_socket_t handle,
RobMeades 0:7ccf0e7e8a83 883 void (*callback)(void *),
RobMeades 0:7ccf0e7e8a83 884 void *data)
RobMeades 0:7ccf0e7e8a83 885 {
RobMeades 0:7ccf0e7e8a83 886 SockCtrl *socket = (SockCtrl *) handle;
RobMeades 0:7ccf0e7e8a83 887
RobMeades 0:7ccf0e7e8a83 888 MBED_ASSERT (check_socket(socket));
RobMeades 0:7ccf0e7e8a83 889
RobMeades 0:7ccf0e7e8a83 890 socket->callback = callback;
RobMeades 0:7ccf0e7e8a83 891 socket->data = data;
RobMeades 0:7ccf0e7e8a83 892 }
RobMeades 0:7ccf0e7e8a83 893
RobMeades 0:7ccf0e7e8a83 894 // Unsupported TCP server functions.
RobMeades 0:7ccf0e7e8a83 895 nsapi_error_t UbloxATCellularInterface::socket_listen(nsapi_socket_t handle,
RobMeades 0:7ccf0e7e8a83 896 int backlog)
RobMeades 0:7ccf0e7e8a83 897 {
RobMeades 0:7ccf0e7e8a83 898 return NSAPI_ERROR_UNSUPPORTED;
RobMeades 0:7ccf0e7e8a83 899 }
RobMeades 0:7ccf0e7e8a83 900 nsapi_error_t UbloxATCellularInterface::socket_accept(nsapi_socket_t server,
RobMeades 0:7ccf0e7e8a83 901 nsapi_socket_t *handle,
RobMeades 0:7ccf0e7e8a83 902 SocketAddress *address)
RobMeades 0:7ccf0e7e8a83 903 {
RobMeades 0:7ccf0e7e8a83 904 return NSAPI_ERROR_UNSUPPORTED;
RobMeades 0:7ccf0e7e8a83 905 }
RobMeades 0:7ccf0e7e8a83 906
RobMeades 0:7ccf0e7e8a83 907 // Unsupported option functions.
RobMeades 0:7ccf0e7e8a83 908 nsapi_error_t UbloxATCellularInterface::setsockopt(nsapi_socket_t handle,
RobMeades 0:7ccf0e7e8a83 909 int level, int optname,
RobMeades 0:7ccf0e7e8a83 910 const void *optval,
RobMeades 0:7ccf0e7e8a83 911 unsigned optlen)
RobMeades 0:7ccf0e7e8a83 912 {
RobMeades 0:7ccf0e7e8a83 913 return NSAPI_ERROR_UNSUPPORTED;
RobMeades 0:7ccf0e7e8a83 914 }
RobMeades 0:7ccf0e7e8a83 915 nsapi_error_t UbloxATCellularInterface::getsockopt(nsapi_socket_t handle,
RobMeades 0:7ccf0e7e8a83 916 int level, int optname,
RobMeades 0:7ccf0e7e8a83 917 void *optval,
RobMeades 0:7ccf0e7e8a83 918 unsigned *optlen)
RobMeades 0:7ccf0e7e8a83 919 {
RobMeades 0:7ccf0e7e8a83 920 return NSAPI_ERROR_UNSUPPORTED;
RobMeades 0:7ccf0e7e8a83 921 }
RobMeades 0:7ccf0e7e8a83 922
RobMeades 0:7ccf0e7e8a83 923 /**********************************************************************
RobMeades 0:7ccf0e7e8a83 924 * PUBLIC METHODS
RobMeades 0:7ccf0e7e8a83 925 **********************************************************************/
RobMeades 0:7ccf0e7e8a83 926
RobMeades 0:7ccf0e7e8a83 927 // Constructor.
RobMeades 0:7ccf0e7e8a83 928 UbloxATCellularInterface::UbloxATCellularInterface(PinName tx,
RobMeades 0:7ccf0e7e8a83 929 PinName rx,
RobMeades 0:7ccf0e7e8a83 930 int baud,
RobMeades 0:7ccf0e7e8a83 931 bool debug_on)
RobMeades 0:7ccf0e7e8a83 932 {
RobMeades 0:7ccf0e7e8a83 933 _sim_pin_check_change_pending = false;
RobMeades 0:7ccf0e7e8a83 934 _sim_pin_check_change_pending_enabled_value = false;
RobMeades 0:7ccf0e7e8a83 935 _sim_pin_change_pending = false;
RobMeades 0:7ccf0e7e8a83 936 _sim_pin_change_pending_new_pin_value = NULL;
RobMeades 0:7ccf0e7e8a83 937 _apn = NULL;
RobMeades 0:7ccf0e7e8a83 938 _uname = NULL;
RobMeades 0:7ccf0e7e8a83 939 _pwd = NULL;
RobMeades 0:7ccf0e7e8a83 940 _connection_status_cb = NULL;
RobMeades 0:7ccf0e7e8a83 941
RobMeades 0:7ccf0e7e8a83 942 // Initialise sockets storage
RobMeades 0:7ccf0e7e8a83 943 memset(_sockets, 0, sizeof(_sockets));
RobMeades 0:7ccf0e7e8a83 944 for (unsigned int socket = 0; socket < sizeof(_sockets) / sizeof(_sockets[0]); socket++) {
RobMeades 0:7ccf0e7e8a83 945 _sockets[socket].modem_handle = SOCKET_UNUSED;
RobMeades 0:7ccf0e7e8a83 946 _sockets[socket].callback = NULL;
RobMeades 0:7ccf0e7e8a83 947 _sockets[socket].data = NULL;
RobMeades 0:7ccf0e7e8a83 948 }
RobMeades 0:7ccf0e7e8a83 949
RobMeades 0:7ccf0e7e8a83 950 // The authentication to use
RobMeades 0:7ccf0e7e8a83 951 _auth = NSAPI_SECURITY_UNKNOWN;
RobMeades 0:7ccf0e7e8a83 952
RobMeades 0:7ccf0e7e8a83 953 // Nullify the temporary IP address storage
RobMeades 0:7ccf0e7e8a83 954 _ip = NULL;
RobMeades 0:7ccf0e7e8a83 955
RobMeades 0:7ccf0e7e8a83 956 // Initialise the base class, which starts the AT parser
RobMeades 0:7ccf0e7e8a83 957 baseClassInit(tx, rx, baud, debug_on);
RobMeades 0:7ccf0e7e8a83 958
RobMeades 0:7ccf0e7e8a83 959 // Start the event handler thread for Rx data
RobMeades 0:7ccf0e7e8a83 960 event_thread.start(callback(this, &UbloxATCellularInterface::handle_event));
RobMeades 0:7ccf0e7e8a83 961
RobMeades 0:7ccf0e7e8a83 962 // URC handlers for sockets
RobMeades 0:7ccf0e7e8a83 963 _at->oob("+UUSORD", callback(this, &UbloxATCellularInterface::UUSORD_URC));
RobMeades 0:7ccf0e7e8a83 964 _at->oob("+UUSORF", callback(this, &UbloxATCellularInterface::UUSORF_URC));
RobMeades 0:7ccf0e7e8a83 965 _at->oob("+UUSOCL", callback(this, &UbloxATCellularInterface::UUSOCL_URC));
RobMeades 0:7ccf0e7e8a83 966 _at->oob("+UUPSDD", callback(this, &UbloxATCellularInterface::UUPSDD_URC));
RobMeades 0:7ccf0e7e8a83 967 }
RobMeades 0:7ccf0e7e8a83 968
RobMeades 0:7ccf0e7e8a83 969 // Destructor.
RobMeades 0:7ccf0e7e8a83 970 UbloxATCellularInterface::~UbloxATCellularInterface()
RobMeades 0:7ccf0e7e8a83 971 {
RobMeades 0:7ccf0e7e8a83 972 // Free _ip if it was ever allocated
RobMeades 0:7ccf0e7e8a83 973 free(_ip);
RobMeades 0:7ccf0e7e8a83 974 }
RobMeades 0:7ccf0e7e8a83 975
RobMeades 0:7ccf0e7e8a83 976 // Set the authentication scheme.
RobMeades 0:7ccf0e7e8a83 977 void UbloxATCellularInterface::set_authentication(nsapi_security_t auth)
RobMeades 0:7ccf0e7e8a83 978 {
RobMeades 0:7ccf0e7e8a83 979 _auth = auth;
RobMeades 0:7ccf0e7e8a83 980 }
RobMeades 0:7ccf0e7e8a83 981
RobMeades 0:7ccf0e7e8a83 982 // Set APN, user name and password.
RobMeades 0:7ccf0e7e8a83 983 void UbloxATCellularInterface::set_credentials(const char *apn,
RobMeades 0:7ccf0e7e8a83 984 const char *uname,
RobMeades 0:7ccf0e7e8a83 985 const char *pwd)
RobMeades 0:7ccf0e7e8a83 986 {
RobMeades 0:7ccf0e7e8a83 987 _apn = apn;
RobMeades 0:7ccf0e7e8a83 988 _uname = uname;
RobMeades 0:7ccf0e7e8a83 989 _pwd = pwd;
RobMeades 0:7ccf0e7e8a83 990 }
RobMeades 0:7ccf0e7e8a83 991
RobMeades 0:7ccf0e7e8a83 992 // Set PIN.
RobMeades 0:7ccf0e7e8a83 993 void UbloxATCellularInterface::set_sim_pin(const char *pin) {
RobMeades 0:7ccf0e7e8a83 994 set_pin(pin);
RobMeades 0:7ccf0e7e8a83 995 }
RobMeades 0:7ccf0e7e8a83 996
rob.meades@u-blox.com 6:63dad754c267 997 static int count = 0;
rob.meades@u-blox.com 6:63dad754c267 998
RobMeades 0:7ccf0e7e8a83 999 // Get the IP address of a host.
RobMeades 0:7ccf0e7e8a83 1000 nsapi_error_t UbloxATCellularInterface::gethostbyname(const char *host,
RobMeades 0:7ccf0e7e8a83 1001 SocketAddress *address,
RobMeades 0:7ccf0e7e8a83 1002 nsapi_version_t version)
RobMeades 0:7ccf0e7e8a83 1003 {
RobMeades 0:7ccf0e7e8a83 1004 nsapi_error_t nsapi_error = NSAPI_ERROR_DEVICE_ERROR;
rob.meades@u-blox.com 6:63dad754c267 1005 int at_timeout;
RobMeades 0:7ccf0e7e8a83 1006 char ipAddress[NSAPI_IP_SIZE];
RobMeades 0:7ccf0e7e8a83 1007
rob.meades@u-blox.com 6:63dad754c267 1008 count++;
RobMeades 0:7ccf0e7e8a83 1009 if (address->set_ip_address(host)) {
RobMeades 0:7ccf0e7e8a83 1010 nsapi_error = NSAPI_ERROR_OK;
RobMeades 0:7ccf0e7e8a83 1011 } else {
RobMeades 0:7ccf0e7e8a83 1012 LOCK();
rob.meades@u-blox.com 6:63dad754c267 1013 // This interrogation can sometimes take longer than the usual 8 seconds
rob.meades@u-blox.com 6:63dad754c267 1014 at_timeout = _at_timeout;
rob.meades@u-blox.com 6:63dad754c267 1015 at_set_timeout(60000);
RobMeades 0:7ccf0e7e8a83 1016 memset (ipAddress, 0, sizeof (ipAddress)); // Ensure terminator
RobMeades 0:7ccf0e7e8a83 1017 if (_at->send("AT+UDNSRN=0,\"%s\"", host) &&
RobMeades 0:7ccf0e7e8a83 1018 _at->recv("+UDNSRN: \"%" u_stringify(NSAPI_IP_SIZE) "[^\"]\"", ipAddress) &&
RobMeades 0:7ccf0e7e8a83 1019 _at->recv("OK")) {
RobMeades 0:7ccf0e7e8a83 1020 if (address->set_ip_address(ipAddress)) {
RobMeades 0:7ccf0e7e8a83 1021 nsapi_error = NSAPI_ERROR_OK;
RobMeades 0:7ccf0e7e8a83 1022 }
RobMeades 0:7ccf0e7e8a83 1023 }
rob.meades@u-blox.com 6:63dad754c267 1024 at_set_timeout(at_timeout);
RobMeades 0:7ccf0e7e8a83 1025 UNLOCK();
RobMeades 0:7ccf0e7e8a83 1026 }
RobMeades 0:7ccf0e7e8a83 1027
RobMeades 0:7ccf0e7e8a83 1028 return nsapi_error;
RobMeades 0:7ccf0e7e8a83 1029 }
RobMeades 0:7ccf0e7e8a83 1030
RobMeades 0:7ccf0e7e8a83 1031 // Make a cellular connection
RobMeades 0:7ccf0e7e8a83 1032 nsapi_error_t UbloxATCellularInterface::connect(const char *sim_pin,
RobMeades 0:7ccf0e7e8a83 1033 const char *apn,
RobMeades 0:7ccf0e7e8a83 1034 const char *uname,
RobMeades 0:7ccf0e7e8a83 1035 const char *pwd)
RobMeades 0:7ccf0e7e8a83 1036 {
RobMeades 0:7ccf0e7e8a83 1037 nsapi_error_t nsapi_error;
RobMeades 0:7ccf0e7e8a83 1038
RobMeades 0:7ccf0e7e8a83 1039 if (sim_pin != NULL) {
RobMeades 0:7ccf0e7e8a83 1040 _pin = sim_pin;
RobMeades 0:7ccf0e7e8a83 1041 }
RobMeades 0:7ccf0e7e8a83 1042
RobMeades 0:7ccf0e7e8a83 1043 if (apn != NULL) {
RobMeades 0:7ccf0e7e8a83 1044 _apn = apn;
RobMeades 0:7ccf0e7e8a83 1045 }
RobMeades 0:7ccf0e7e8a83 1046
RobMeades 0:7ccf0e7e8a83 1047 if ((uname != NULL) && (pwd != NULL)) {
RobMeades 0:7ccf0e7e8a83 1048 _uname = uname;
RobMeades 0:7ccf0e7e8a83 1049 _pwd = pwd;
RobMeades 0:7ccf0e7e8a83 1050 } else {
RobMeades 0:7ccf0e7e8a83 1051 _uname = NULL;
RobMeades 0:7ccf0e7e8a83 1052 _pwd = NULL;
RobMeades 0:7ccf0e7e8a83 1053 }
RobMeades 0:7ccf0e7e8a83 1054
RobMeades 0:7ccf0e7e8a83 1055 nsapi_error = connect();
RobMeades 0:7ccf0e7e8a83 1056
RobMeades 0:7ccf0e7e8a83 1057 return nsapi_error;
RobMeades 0:7ccf0e7e8a83 1058 }
RobMeades 0:7ccf0e7e8a83 1059
RobMeades 0:7ccf0e7e8a83 1060 // Make a cellular connection using the IP stack on board the cellular modem
RobMeades 0:7ccf0e7e8a83 1061 nsapi_error_t UbloxATCellularInterface::connect()
RobMeades 0:7ccf0e7e8a83 1062 {
RobMeades 0:7ccf0e7e8a83 1063 nsapi_error_t nsapi_error = NSAPI_ERROR_DEVICE_ERROR;
RobMeades 0:7ccf0e7e8a83 1064 bool registered = false;
RobMeades 0:7ccf0e7e8a83 1065
RobMeades 0:7ccf0e7e8a83 1066 // Set up modem and then register with the network
RobMeades 0:7ccf0e7e8a83 1067 if (init()) {
RobMeades 0:7ccf0e7e8a83 1068 nsapi_error = NSAPI_ERROR_NO_CONNECTION;
RobMeades 0:7ccf0e7e8a83 1069 // Perform any pending SIM actions
RobMeades 0:7ccf0e7e8a83 1070 if (_sim_pin_check_change_pending) {
RobMeades 0:7ccf0e7e8a83 1071 if (!sim_pin_check_enable(_sim_pin_check_change_pending_enabled_value)) {
RobMeades 0:7ccf0e7e8a83 1072 nsapi_error = NSAPI_ERROR_AUTH_FAILURE;
RobMeades 0:7ccf0e7e8a83 1073 }
RobMeades 0:7ccf0e7e8a83 1074 _sim_pin_check_change_pending = false;
RobMeades 0:7ccf0e7e8a83 1075 }
RobMeades 0:7ccf0e7e8a83 1076 if (_sim_pin_change_pending) {
RobMeades 0:7ccf0e7e8a83 1077 if (!change_sim_pin(_sim_pin_change_pending_new_pin_value)) {
RobMeades 0:7ccf0e7e8a83 1078 nsapi_error = NSAPI_ERROR_AUTH_FAILURE;
RobMeades 0:7ccf0e7e8a83 1079 }
RobMeades 0:7ccf0e7e8a83 1080 _sim_pin_change_pending = false;
RobMeades 0:7ccf0e7e8a83 1081 }
RobMeades 0:7ccf0e7e8a83 1082
RobMeades 0:7ccf0e7e8a83 1083 if (nsapi_error == NSAPI_ERROR_NO_CONNECTION) {
RobMeades 0:7ccf0e7e8a83 1084 for (int retries = 0; !registered && (retries < 3); retries++) {
RobMeades 0:7ccf0e7e8a83 1085 if (nwk_registration()) {
RobMeades 0:7ccf0e7e8a83 1086 registered = true;;
RobMeades 0:7ccf0e7e8a83 1087 }
RobMeades 0:7ccf0e7e8a83 1088 }
RobMeades 0:7ccf0e7e8a83 1089 }
RobMeades 0:7ccf0e7e8a83 1090 }
RobMeades 0:7ccf0e7e8a83 1091
RobMeades 0:7ccf0e7e8a83 1092 // Attempt to establish a connection
RobMeades 0:7ccf0e7e8a83 1093 if (registered && connect_modem_stack()) {
RobMeades 0:7ccf0e7e8a83 1094 nsapi_error = NSAPI_ERROR_OK;
RobMeades 0:7ccf0e7e8a83 1095 }
RobMeades 0:7ccf0e7e8a83 1096
RobMeades 0:7ccf0e7e8a83 1097 return nsapi_error;
RobMeades 0:7ccf0e7e8a83 1098 }
RobMeades 0:7ccf0e7e8a83 1099
RobMeades 0:7ccf0e7e8a83 1100 // User initiated disconnect.
RobMeades 0:7ccf0e7e8a83 1101 nsapi_error_t UbloxATCellularInterface::disconnect()
RobMeades 0:7ccf0e7e8a83 1102 {
RobMeades 0:7ccf0e7e8a83 1103 nsapi_error_t nsapi_error = NSAPI_ERROR_DEVICE_ERROR;
RobMeades 0:7ccf0e7e8a83 1104
RobMeades 0:7ccf0e7e8a83 1105 if (disconnect_modem_stack() && nwk_deregistration()) {
RobMeades 0:7ccf0e7e8a83 1106 nsapi_error = NSAPI_ERROR_OK;
RobMeades 0:7ccf0e7e8a83 1107 }
RobMeades 0:7ccf0e7e8a83 1108
RobMeades 0:7ccf0e7e8a83 1109 return nsapi_error;
RobMeades 0:7ccf0e7e8a83 1110 }
RobMeades 0:7ccf0e7e8a83 1111
RobMeades 0:7ccf0e7e8a83 1112 // Enable or disable SIM PIN check lock.
RobMeades 0:7ccf0e7e8a83 1113 nsapi_error_t UbloxATCellularInterface::set_sim_pin_check(bool set,
RobMeades 0:7ccf0e7e8a83 1114 bool immediate,
RobMeades 0:7ccf0e7e8a83 1115 const char *sim_pin)
RobMeades 0:7ccf0e7e8a83 1116 {
RobMeades 0:7ccf0e7e8a83 1117 nsapi_error_t nsapi_error = NSAPI_ERROR_AUTH_FAILURE;
RobMeades 0:7ccf0e7e8a83 1118
RobMeades 0:7ccf0e7e8a83 1119 if (sim_pin != NULL) {
RobMeades 0:7ccf0e7e8a83 1120 _pin = sim_pin;
RobMeades 0:7ccf0e7e8a83 1121 }
RobMeades 0:7ccf0e7e8a83 1122
RobMeades 0:7ccf0e7e8a83 1123 if (immediate) {
RobMeades 0:7ccf0e7e8a83 1124 if (init()) {
RobMeades 0:7ccf0e7e8a83 1125 if (sim_pin_check_enable(set)) {
RobMeades 0:7ccf0e7e8a83 1126 nsapi_error = NSAPI_ERROR_OK;
RobMeades 0:7ccf0e7e8a83 1127 }
RobMeades 0:7ccf0e7e8a83 1128 } else {
RobMeades 0:7ccf0e7e8a83 1129 nsapi_error = NSAPI_ERROR_DEVICE_ERROR;
RobMeades 0:7ccf0e7e8a83 1130 }
RobMeades 0:7ccf0e7e8a83 1131 } else {
RobMeades 0:7ccf0e7e8a83 1132 nsapi_error = NSAPI_ERROR_OK;
RobMeades 0:7ccf0e7e8a83 1133 _sim_pin_check_change_pending = true;
RobMeades 0:7ccf0e7e8a83 1134 _sim_pin_check_change_pending_enabled_value = set;
RobMeades 0:7ccf0e7e8a83 1135 }
RobMeades 0:7ccf0e7e8a83 1136
RobMeades 0:7ccf0e7e8a83 1137 return nsapi_error;
RobMeades 0:7ccf0e7e8a83 1138 }
RobMeades 0:7ccf0e7e8a83 1139
RobMeades 0:7ccf0e7e8a83 1140 // Change the PIN code for the SIM card.
RobMeades 0:7ccf0e7e8a83 1141 nsapi_error_t UbloxATCellularInterface::set_new_sim_pin(const char *new_pin,
RobMeades 0:7ccf0e7e8a83 1142 bool immediate,
RobMeades 0:7ccf0e7e8a83 1143 const char *old_pin)
RobMeades 0:7ccf0e7e8a83 1144 {
RobMeades 0:7ccf0e7e8a83 1145 nsapi_error_t nsapi_error = NSAPI_ERROR_AUTH_FAILURE;
RobMeades 0:7ccf0e7e8a83 1146
RobMeades 0:7ccf0e7e8a83 1147 if (old_pin != NULL) {
RobMeades 0:7ccf0e7e8a83 1148 _pin = old_pin;
RobMeades 0:7ccf0e7e8a83 1149 }
RobMeades 0:7ccf0e7e8a83 1150
RobMeades 0:7ccf0e7e8a83 1151 if (immediate) {
RobMeades 0:7ccf0e7e8a83 1152 if (init()) {
RobMeades 0:7ccf0e7e8a83 1153 if (change_sim_pin(new_pin)) {
RobMeades 0:7ccf0e7e8a83 1154 nsapi_error = NSAPI_ERROR_OK;
RobMeades 0:7ccf0e7e8a83 1155 }
RobMeades 0:7ccf0e7e8a83 1156 } else {
RobMeades 0:7ccf0e7e8a83 1157 nsapi_error = NSAPI_ERROR_DEVICE_ERROR;
RobMeades 0:7ccf0e7e8a83 1158 }
RobMeades 0:7ccf0e7e8a83 1159 } else {
RobMeades 0:7ccf0e7e8a83 1160 nsapi_error = NSAPI_ERROR_OK;
RobMeades 0:7ccf0e7e8a83 1161 _sim_pin_change_pending = true;
RobMeades 0:7ccf0e7e8a83 1162 _sim_pin_change_pending_new_pin_value = new_pin;
RobMeades 0:7ccf0e7e8a83 1163 }
RobMeades 0:7ccf0e7e8a83 1164
RobMeades 0:7ccf0e7e8a83 1165 return nsapi_error;
RobMeades 0:7ccf0e7e8a83 1166 }
RobMeades 0:7ccf0e7e8a83 1167
RobMeades 0:7ccf0e7e8a83 1168 // Determine if the connection is up.
RobMeades 0:7ccf0e7e8a83 1169 bool UbloxATCellularInterface::is_connected()
RobMeades 0:7ccf0e7e8a83 1170 {
RobMeades 0:7ccf0e7e8a83 1171 return get_ip_address() != NULL;
RobMeades 0:7ccf0e7e8a83 1172 }
RobMeades 0:7ccf0e7e8a83 1173
RobMeades 0:7ccf0e7e8a83 1174 // Get the IP address of the on-board modem IP stack.
RobMeades 0:7ccf0e7e8a83 1175 const char * UbloxATCellularInterface::get_ip_address()
RobMeades 0:7ccf0e7e8a83 1176 {
RobMeades 0:7ccf0e7e8a83 1177 SocketAddress address;
RobMeades 0:7ccf0e7e8a83 1178 LOCK();
RobMeades 0:7ccf0e7e8a83 1179
RobMeades 0:7ccf0e7e8a83 1180 if (_ip == NULL) {
RobMeades 0:7ccf0e7e8a83 1181 // Temporary storage for an IP address string with terminator
RobMeades 0:7ccf0e7e8a83 1182 _ip = (char *) malloc(NSAPI_IP_SIZE);
RobMeades 0:7ccf0e7e8a83 1183 }
RobMeades 0:7ccf0e7e8a83 1184
RobMeades 0:7ccf0e7e8a83 1185 if (_ip != NULL) {
RobMeades 0:7ccf0e7e8a83 1186 memset(_ip, 0, NSAPI_IP_SIZE); // Ensure a terminator
RobMeades 0:7ccf0e7e8a83 1187 // +UPSND=<profile_id>,<param_tag>[,<dynamic_param_val>]
RobMeades 0:7ccf0e7e8a83 1188 // If we get back a quoted "w.x.y.z" then we have an IP address,
RobMeades 0:7ccf0e7e8a83 1189 // otherwise we don't.
RobMeades 0:7ccf0e7e8a83 1190 if (!_at->send("AT+UPSND=" PROFILE ",0") ||
RobMeades 0:7ccf0e7e8a83 1191 !_at->recv("+UPSND: " PROFILE ",0,\"%" u_stringify(NSAPI_IP_SIZE) "[^\"]\"", _ip) ||
RobMeades 0:7ccf0e7e8a83 1192 !_at->recv("OK") ||
RobMeades 0:7ccf0e7e8a83 1193 !address.set_ip_address(_ip) || // Return NULL if the address is not a valid one
RobMeades 0:7ccf0e7e8a83 1194 !address) { // Return null if the address is zero
RobMeades 0:7ccf0e7e8a83 1195 free (_ip);
RobMeades 0:7ccf0e7e8a83 1196 _ip = NULL;
RobMeades 0:7ccf0e7e8a83 1197 }
RobMeades 0:7ccf0e7e8a83 1198 }
RobMeades 0:7ccf0e7e8a83 1199
RobMeades 0:7ccf0e7e8a83 1200 UNLOCK();
RobMeades 0:7ccf0e7e8a83 1201 return _ip;
RobMeades 0:7ccf0e7e8a83 1202 }
RobMeades 0:7ccf0e7e8a83 1203
RobMeades 0:7ccf0e7e8a83 1204 // Get the local network mask.
RobMeades 0:7ccf0e7e8a83 1205 const char *UbloxATCellularInterface::get_netmask()
RobMeades 0:7ccf0e7e8a83 1206 {
RobMeades 0:7ccf0e7e8a83 1207 // Not implemented.
RobMeades 0:7ccf0e7e8a83 1208 return NULL;
RobMeades 0:7ccf0e7e8a83 1209 }
RobMeades 0:7ccf0e7e8a83 1210
RobMeades 0:7ccf0e7e8a83 1211 // Get the local gateways.
RobMeades 0:7ccf0e7e8a83 1212 const char *UbloxATCellularInterface::get_gateway()
RobMeades 0:7ccf0e7e8a83 1213 {
RobMeades 0:7ccf0e7e8a83 1214 return get_ip_address();
RobMeades 0:7ccf0e7e8a83 1215 }
RobMeades 0:7ccf0e7e8a83 1216
RobMeades 0:7ccf0e7e8a83 1217 // Callback in case the connection is lost.
RobMeades 0:7ccf0e7e8a83 1218 void UbloxATCellularInterface::connection_status_cb(Callback<void(nsapi_error_t)> cb)
RobMeades 0:7ccf0e7e8a83 1219 {
RobMeades 0:7ccf0e7e8a83 1220 _connection_status_cb = cb;
RobMeades 0:7ccf0e7e8a83 1221 }
RobMeades 0:7ccf0e7e8a83 1222
RobMeades 0:7ccf0e7e8a83 1223 // End of file
RobMeades 0:7ccf0e7e8a83 1224