Fork of ublox-at-cellular-interface to add LARA-R2 support

Dependents:  

Fork of ublox-at-cellular-interface by u-blox

Committer:
cblack
Date:
Thu Sep 27 15:45:38 2018 -0500
Revision:
19:2e961ce171e6
Parent:
18:bfc869299185
Fix to hex mode workaround - read 2x the size in hex mode

Who changed what in which revision?

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