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:
fahim.alavi@u-blox.com
Date:
Wed Jan 30 16:37:21 2019 +0500
Revision:
19:7013521e75e7
Parent:
18:1f34f8d0c850
Child:
21:2a500a881a5a
Child:
24:35d5b2a02df8
Made changes not to disconnect modem stack for target C030-R41xM

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