ublox-at-cellular-interface_tests

Committer:
wajahat.abbas@u-blox.com
Date:
Mon Sep 23 15:13:42 2019 +0500
Revision:
38:7d053638b3f1
Parent:
36:9d48ec522cb4
Updated test cases

Who changed what in which revision?

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