Implementation of the CellularInterface for u-blox C027 and C030 (non-N2xx flavour) modems that uses the IP stack on-board the cellular modem, hence not requiring LWIP (and so less RAM) and allowing any AT command exchanges to be carried out at the same time as data transfers (since the modem remains in AT mode all the time). This library may be used from mbed 5.5 onwards. If you need to use SMS, USSD or access the modem file system at the same time as using the CellularInterface then use ublox-at-cellular-interface-ext instead.

Dependents:   example-ublox-cellular-interface example-ublox-cellular-interface_r410M example-ublox-mbed-client example-ublox-cellular-interface ... more

Committer:
fahimalavi
Date:
Wed Jan 01 11:47:24 2020 +0500
Revision:
41:69998003d95a
Parent:
37:0ceb2dfc746c
Child:
42:98808477a691
mbed-os 5.15: String-based APIs are deprecated

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 37:0ceb2dfc746c 349
wajahat.abbas@u-blox.com 37:0ceb2dfc746c 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
fahimalavi 41:69998003d95a 1382 // Get the IP address of the on-board modem IP stack.
fahimalavi 41:69998003d95a 1383 nsapi_error_t UbloxATCellularInterface::get_ip_address(SocketAddress *address)
fahimalavi 41:69998003d95a 1384 {
fahimalavi 41:69998003d95a 1385 address->set_ip_address(this->get_ip_address());
fahimalavi 41:69998003d95a 1386
fahimalavi 41:69998003d95a 1387 return NSAPI_ERROR_OK;
fahimalavi 41:69998003d95a 1388 }
fahimalavi 41:69998003d95a 1389
fahimalavi 41:69998003d95a 1390 nsapi_error_t UbloxATCellularInterface::get_netmask(SocketAddress *address)
fahimalavi 41:69998003d95a 1391 {
fahimalavi 41:69998003d95a 1392 address->set_ip_address("");
fahimalavi 41:69998003d95a 1393
fahimalavi 41:69998003d95a 1394 return NSAPI_ERROR_OK;
fahimalavi 41:69998003d95a 1395 }
fahimalavi 41:69998003d95a 1396
fahimalavi 41:69998003d95a 1397 nsapi_error_t UbloxATCellularInterface::get_gateway(SocketAddress *address)
fahimalavi 41:69998003d95a 1398 {
fahimalavi 41:69998003d95a 1399 address->set_ip_address(this->get_ip_address());
fahimalavi 41:69998003d95a 1400
fahimalavi 41:69998003d95a 1401 return NSAPI_ERROR_OK;
fahimalavi 41:69998003d95a 1402 }
fahimalavi 41:69998003d95a 1403
RobMeades 0:7ccf0e7e8a83 1404 // Get the local network mask.
RobMeades 0:7ccf0e7e8a83 1405 const char *UbloxATCellularInterface::get_netmask()
RobMeades 0:7ccf0e7e8a83 1406 {
RobMeades 0:7ccf0e7e8a83 1407 // Not implemented.
RobMeades 0:7ccf0e7e8a83 1408 return NULL;
RobMeades 0:7ccf0e7e8a83 1409 }
RobMeades 0:7ccf0e7e8a83 1410
RobMeades 0:7ccf0e7e8a83 1411 // Get the local gateways.
RobMeades 0:7ccf0e7e8a83 1412 const char *UbloxATCellularInterface::get_gateway()
RobMeades 0:7ccf0e7e8a83 1413 {
RobMeades 0:7ccf0e7e8a83 1414 return get_ip_address();
RobMeades 0:7ccf0e7e8a83 1415 }
RobMeades 0:7ccf0e7e8a83 1416
RobMeades 0:7ccf0e7e8a83 1417 // Callback in case the connection is lost.
RobMeades 0:7ccf0e7e8a83 1418 void UbloxATCellularInterface::connection_status_cb(Callback<void(nsapi_error_t)> cb)
RobMeades 0:7ccf0e7e8a83 1419 {
RobMeades 0:7ccf0e7e8a83 1420 _connection_status_cb = cb;
RobMeades 0:7ccf0e7e8a83 1421 }
RobMeades 0:7ccf0e7e8a83 1422
fahim.alavi@u-blox.com 17:7b033423126c 1423 void UbloxATCellularInterface::set_plmn(const char *plmn) {
fahim.alavi@u-blox.com 17:7b033423126c 1424
fahim.alavi@u-blox.com 17:7b033423126c 1425 }
fahim.alavi@u-blox.com 17:7b033423126c 1426
RobMeades 0:7ccf0e7e8a83 1427 // End of file
RobMeades 0:7ccf0e7e8a83 1428