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:
SanaMasood
Date:
Wed May 08 14:54:33 2019 +0500
Revision:
21:2a500a881a5a
Parent:
19:7013521e75e7
Child:
25:aabc50bc418e
static warning removed

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