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:
wajahat.abbas@u-blox.com
Date:
Mon Aug 19 17:36:04 2019 +0500
Revision:
36:9d48ec522cb4
Parent:
34:ca02f8448085
Child:
37:0ceb2dfc746c
Fix to read OK as well

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;
RobMeades 0:7ccf0e7e8a83 349 int at_timeout = _at_timeout;
RobMeades 0:7ccf0e7e8a83 350
wajahat.abbas@u-blox.com 24:35d5b2a02df8 351 #ifndef TARGET_UBLOX_C030_R41XM
RobMeades 0:7ccf0e7e8a83 352 if (_at->send("AT+CGDCONT=%d,\"IP\",\"%s\"", cid, apn) && _at->recv("OK") &&
RobMeades 0:7ccf0e7e8a83 353 _at->send("AT+UAUTHREQ=%d,%d,\"%s\",\"%s\"", cid, nsapi_security_to_modem_security(auth),
RobMeades 0:7ccf0e7e8a83 354 username, password) && _at->recv("OK") &&
RobMeades 0:7ccf0e7e8a83 355 _at->send("AT+UPSD=" PROFILE ",100,%d", cid) && _at->recv("OK")) {
RobMeades 0:7ccf0e7e8a83 356
RobMeades 0:7ccf0e7e8a83 357 // Wait 30 seconds for the connection to be made
RobMeades 0:7ccf0e7e8a83 358 at_set_timeout(30000);
RobMeades 0:7ccf0e7e8a83 359 // Activate the protocol
RobMeades 0:7ccf0e7e8a83 360 success = _at->send("AT+UPSDA=" PROFILE ",3") && _at->recv("OK");
RobMeades 0:7ccf0e7e8a83 361 at_set_timeout(at_timeout);
RobMeades 0:7ccf0e7e8a83 362 }
wajahat.abbas@u-blox.com 24:35d5b2a02df8 363 #else
wajahat.abbas@u-blox.com 24:35d5b2a02df8 364 int modem_security = nsapi_security_to_modem_security(auth);
wajahat.abbas@u-blox.com 24:35d5b2a02df8 365 if (_at->send("AT+CGDCONT=%d,\"IP\",\"%s\"", cid, apn) && _at->recv("OK")) {
wajahat.abbas@u-blox.com 24:35d5b2a02df8 366 if ( modem_security == NSAPI_SECURITY_CHAP) {
wajahat.abbas@u-blox.com 24:35d5b2a02df8 367 if (_at->send("AT+UAUTHREQ=%d,%d,\"%s\",\"%s\"", cid, modem_security,
wajahat.abbas@u-blox.com 24:35d5b2a02df8 368 password, username) && _at->recv("OK")) {
wajahat.abbas@u-blox.com 24:35d5b2a02df8 369 success = true;
wajahat.abbas@u-blox.com 24:35d5b2a02df8 370 }
wajahat.abbas@u-blox.com 24:35d5b2a02df8 371 } else if (modem_security == NSAPI_SECURITY_NONE) {
wajahat.abbas@u-blox.com 24:35d5b2a02df8 372 if (_at->send("AT+UAUTHREQ=%d,%d", cid, modem_security) && _at->recv("OK")) {
wajahat.abbas@u-blox.com 24:35d5b2a02df8 373 success = true;
wajahat.abbas@u-blox.com 24:35d5b2a02df8 374 }
wajahat.abbas@u-blox.com 24:35d5b2a02df8 375 } else {
wajahat.abbas@u-blox.com 24:35d5b2a02df8 376 if (_at->send("AT+UAUTHREQ=%d,%d,\"%s\",\"%s\"", cid, modem_security,
wajahat.abbas@u-blox.com 24:35d5b2a02df8 377 username, password) && _at->recv("OK")) {
wajahat.abbas@u-blox.com 24:35d5b2a02df8 378 success = true;
wajahat.abbas@u-blox.com 24:35d5b2a02df8 379 }
wajahat.abbas@u-blox.com 24:35d5b2a02df8 380 }
wajahat.abbas@u-blox.com 24:35d5b2a02df8 381 }
wajahat.abbas@u-blox.com 24:35d5b2a02df8 382 #endif
RobMeades 0:7ccf0e7e8a83 383
RobMeades 0:7ccf0e7e8a83 384 return success;
RobMeades 0:7ccf0e7e8a83 385 }
RobMeades 0:7ccf0e7e8a83 386
wajahat.abbas@u-blox.com 24:35d5b2a02df8 387 #ifdef TARGET_UBLOX_C030_R41XM
wajahat.abbas@u-blox.com 24:35d5b2a02df8 388 //define PDP context for R412M
wajahat.abbas@u-blox.com 24:35d5b2a02df8 389 bool UbloxATCellularInterface::define_context()
wajahat.abbas@u-blox.com 24:35d5b2a02df8 390 {
wajahat.abbas@u-blox.com 24:35d5b2a02df8 391 bool success = false;
wajahat.abbas@u-blox.com 24:35d5b2a02df8 392 const char * config = NULL;
wajahat.abbas@u-blox.com 24:35d5b2a02df8 393 LOCK();
wajahat.abbas@u-blox.com 24:35d5b2a02df8 394
wajahat.abbas@u-blox.com 24:35d5b2a02df8 395 // If the caller hasn't entered an APN, try to find it
wajahat.abbas@u-blox.com 24:35d5b2a02df8 396 if (_apn == NULL) {
wajahat.abbas@u-blox.com 24:35d5b2a02df8 397 config = apnconfig(_dev_info.imsi);
wajahat.abbas@u-blox.com 24:35d5b2a02df8 398 }
wajahat.abbas@u-blox.com 24:35d5b2a02df8 399
wajahat.abbas@u-blox.com 24:35d5b2a02df8 400 // Attempt to connect
wajahat.abbas@u-blox.com 24:35d5b2a02df8 401 do {
wajahat.abbas@u-blox.com 24:35d5b2a02df8 402 // Set up APN and IP protocol for PDP context
wajahat.abbas@u-blox.com 24:35d5b2a02df8 403 get_next_credentials(&config);
wajahat.abbas@u-blox.com 24:35d5b2a02df8 404 _auth = (*_uname && *_pwd) ? _auth : NSAPI_SECURITY_NONE;
wajahat.abbas@u-blox.com 24:35d5b2a02df8 405 if (activate_profile_by_cid(1, _apn, _uname, _pwd, _auth)) {
wajahat.abbas@u-blox.com 24:35d5b2a02df8 406 success = true;
wajahat.abbas@u-blox.com 24:35d5b2a02df8 407 }
wajahat.abbas@u-blox.com 24:35d5b2a02df8 408 } while (!success && config && *config);
wajahat.abbas@u-blox.com 24:35d5b2a02df8 409
wajahat.abbas@u-blox.com 24:35d5b2a02df8 410 if (!success) {
wajahat.abbas@u-blox.com 24:35d5b2a02df8 411 tr_error("Failed to connect, check your APN/username/password");
wajahat.abbas@u-blox.com 24:35d5b2a02df8 412 }
wajahat.abbas@u-blox.com 24:35d5b2a02df8 413
wajahat.abbas@u-blox.com 24:35d5b2a02df8 414 UNLOCK();
wajahat.abbas@u-blox.com 24:35d5b2a02df8 415 return success;
wajahat.abbas@u-blox.com 24:35d5b2a02df8 416 }
wajahat.abbas@u-blox.com 24:35d5b2a02df8 417 bool UbloxATCellularInterface::activate_context()
wajahat.abbas@u-blox.com 24:35d5b2a02df8 418 {
wajahat.abbas@u-blox.com 24:35d5b2a02df8 419 bool status = false;
wajahat.abbas@u-blox.com 24:35d5b2a02df8 420 int at_timeout;
wajahat.abbas@u-blox.com 24:35d5b2a02df8 421 LOCK();
wajahat.abbas@u-blox.com 24:35d5b2a02df8 422
wajahat.abbas@u-blox.com 24:35d5b2a02df8 423 at_timeout = _at_timeout; // Has to be inside LOCK()s
wajahat.abbas@u-blox.com 24:35d5b2a02df8 424 at_set_timeout(150000);
wajahat.abbas@u-blox.com 24:35d5b2a02df8 425 if (_at->send("AT+CGACT=1,1") && _at->recv("OK")) {
wajahat.abbas@u-blox.com 24:35d5b2a02df8 426 status = true;
wajahat.abbas@u-blox.com 24:35d5b2a02df8 427 }
wajahat.abbas@u-blox.com 24:35d5b2a02df8 428
wajahat.abbas@u-blox.com 24:35d5b2a02df8 429 at_set_timeout(at_timeout);
wajahat.abbas@u-blox.com 24:35d5b2a02df8 430
wajahat.abbas@u-blox.com 24:35d5b2a02df8 431 UNLOCK();
wajahat.abbas@u-blox.com 24:35d5b2a02df8 432 return status;
wajahat.abbas@u-blox.com 24:35d5b2a02df8 433 }
wajahat.abbas@u-blox.com 34:ca02f8448085 434
wajahat.abbas@u-blox.com 34:ca02f8448085 435 bool UbloxATCellularInterface::is_context_active()
wajahat.abbas@u-blox.com 34:ca02f8448085 436 {
wajahat.abbas@u-blox.com 34:ca02f8448085 437 bool status = false;
wajahat.abbas@u-blox.com 34:ca02f8448085 438 int at_timeout;
wajahat.abbas@u-blox.com 34:ca02f8448085 439 int active = 0;
wajahat.abbas@u-blox.com 34:ca02f8448085 440 LOCK();
wajahat.abbas@u-blox.com 34:ca02f8448085 441
wajahat.abbas@u-blox.com 34:ca02f8448085 442 at_timeout = _at_timeout; // Has to be inside LOCK()s
wajahat.abbas@u-blox.com 34:ca02f8448085 443 at_set_timeout(150000);
wajahat.abbas@u-blox.com 36:9d48ec522cb4 444 if (_at->send("AT+CGACT?") && _at->recv("+CGACT: %*d,%d\n", &active) &&
wajahat.abbas@u-blox.com 36:9d48ec522cb4 445 _at->recv("OK")) {
wajahat.abbas@u-blox.com 34:ca02f8448085 446 if (active == 1) {
wajahat.abbas@u-blox.com 34:ca02f8448085 447 status = true;
wajahat.abbas@u-blox.com 34:ca02f8448085 448 }
wajahat.abbas@u-blox.com 34:ca02f8448085 449 }
wajahat.abbas@u-blox.com 34:ca02f8448085 450 at_set_timeout(at_timeout);
wajahat.abbas@u-blox.com 34:ca02f8448085 451
wajahat.abbas@u-blox.com 34:ca02f8448085 452 UNLOCK();
wajahat.abbas@u-blox.com 34:ca02f8448085 453 return status;
wajahat.abbas@u-blox.com 34:ca02f8448085 454 }
wajahat.abbas@u-blox.com 24:35d5b2a02df8 455 #endif
wajahat.abbas@u-blox.com 24:35d5b2a02df8 456
RobMeades 0:7ccf0e7e8a83 457 // Connect the on board IP stack of the modem.
RobMeades 0:7ccf0e7e8a83 458 bool UbloxATCellularInterface::connect_modem_stack()
RobMeades 0:7ccf0e7e8a83 459 {
RobMeades 0:7ccf0e7e8a83 460 bool success = false;
RobMeades 0:7ccf0e7e8a83 461 int active = 0;
RobMeades 0:7ccf0e7e8a83 462 const char * config = NULL;
RobMeades 0:7ccf0e7e8a83 463 LOCK();
RobMeades 0:7ccf0e7e8a83 464
RobMeades 0:7ccf0e7e8a83 465 // Check the profile
RobMeades 0:7ccf0e7e8a83 466 if (_at->send("AT+UPSND=" PROFILE ",8") && _at->recv("+UPSND: %*d,%*d,%d\n", &active) &&
RobMeades 0:7ccf0e7e8a83 467 _at->recv("OK")) {
RobMeades 0:7ccf0e7e8a83 468 if (active == 0) {
RobMeades 0:7ccf0e7e8a83 469 // If the caller hasn't entered an APN, try to find it
RobMeades 0:7ccf0e7e8a83 470 if (_apn == NULL) {
RobMeades 0:7ccf0e7e8a83 471 config = apnconfig(_dev_info.imsi);
RobMeades 0:7ccf0e7e8a83 472 }
RobMeades 0:7ccf0e7e8a83 473
RobMeades 0:7ccf0e7e8a83 474 // Attempt to connect
RobMeades 0:7ccf0e7e8a83 475 do {
RobMeades 0:7ccf0e7e8a83 476 // Set up APN and IP protocol for PDP context
rob.meades@u-blox.com 7:3b2ca10cc23a 477 get_next_credentials(&config);
RobMeades 0:7ccf0e7e8a83 478 _auth = (*_uname && *_pwd) ? _auth : NSAPI_SECURITY_NONE;
RobMeades 0:7ccf0e7e8a83 479 if ((_dev_info.dev != DEV_TOBY_L2) && (_dev_info.dev != DEV_MPCI_L2)) {
RobMeades 0:7ccf0e7e8a83 480 success = activate_profile(_apn, _uname, _pwd, _auth);
RobMeades 0:7ccf0e7e8a83 481 } else {
RobMeades 0:7ccf0e7e8a83 482 success = activate_profile_reuse_external();
RobMeades 0:7ccf0e7e8a83 483 if (success) {
RobMeades 0:7ccf0e7e8a83 484 tr_debug("Reusing external context");
RobMeades 0:7ccf0e7e8a83 485 } else {
RobMeades 0:7ccf0e7e8a83 486 success = activate_profile_by_cid(1, _apn, _uname, _pwd, _auth);
RobMeades 0:7ccf0e7e8a83 487 }
RobMeades 0:7ccf0e7e8a83 488 }
RobMeades 0:7ccf0e7e8a83 489 } while (!success && config && *config);
RobMeades 0:7ccf0e7e8a83 490 } else {
RobMeades 0:7ccf0e7e8a83 491 // If the profile is already active, we're good
RobMeades 0:7ccf0e7e8a83 492 success = true;
RobMeades 0:7ccf0e7e8a83 493 }
RobMeades 0:7ccf0e7e8a83 494 }
RobMeades 0:7ccf0e7e8a83 495
RobMeades 0:7ccf0e7e8a83 496 if (!success) {
RobMeades 0:7ccf0e7e8a83 497 tr_error("Failed to connect, check your APN/username/password");
RobMeades 0:7ccf0e7e8a83 498 }
RobMeades 0:7ccf0e7e8a83 499
RobMeades 0:7ccf0e7e8a83 500 UNLOCK();
RobMeades 0:7ccf0e7e8a83 501 return success;
RobMeades 0:7ccf0e7e8a83 502 }
RobMeades 0:7ccf0e7e8a83 503
RobMeades 0:7ccf0e7e8a83 504 // Disconnect the on board IP stack of the modem.
RobMeades 0:7ccf0e7e8a83 505 bool UbloxATCellularInterface::disconnect_modem_stack()
RobMeades 0:7ccf0e7e8a83 506 {
RobMeades 0:7ccf0e7e8a83 507 bool success = false;
fahimalavi 30:0f571a4920c8 508 int active;
fahimalavi 30:0f571a4920c8 509 Timer t1;
RobMeades 0:7ccf0e7e8a83 510 LOCK();
RobMeades 0:7ccf0e7e8a83 511
RobMeades 0:7ccf0e7e8a83 512 if (get_ip_address() != NULL) {
RobMeades 0:7ccf0e7e8a83 513 if (_at->send("AT+UPSDA=" PROFILE ",4") && _at->recv("OK")) {
RobMeades 0:7ccf0e7e8a83 514 success = true;
RobMeades 0:7ccf0e7e8a83 515 if (_connection_status_cb) {
RobMeades 0:7ccf0e7e8a83 516 _connection_status_cb(NSAPI_ERROR_CONNECTION_LOST);
RobMeades 0:7ccf0e7e8a83 517 }
RobMeades 0:7ccf0e7e8a83 518 }
RobMeades 0:7ccf0e7e8a83 519 }
fahimalavi 30:0f571a4920c8 520 t1.start();
fahimalavi 30:0f571a4920c8 521 while (!(t1.read() >= 180)) {
fahimalavi 30:0f571a4920c8 522 if (_at->send("AT+UPSND=" PROFILE ",8") && _at->recv("+UPSND: %*d,%*d,%d\n", &active) && _at->recv("OK")) {
fahimalavi 30:0f571a4920c8 523
fahimalavi 30:0f571a4920c8 524 if (active == 0) { //If context is deactivated, exit while loop and return status
fahimalavi 30:0f571a4920c8 525 tr_debug("Profile deactivated successfully");
fahimalavi 30:0f571a4920c8 526 break;
fahimalavi 30:0f571a4920c8 527 }
fahimalavi 30:0f571a4920c8 528 else {
fahimalavi 30:0f571a4920c8 529 tr_error("Profile still active");
fahimalavi 30:0f571a4920c8 530 rtos::ThisThread::sleep_for(5000); //Wait for 5 seconds and then try again
fahimalavi 30:0f571a4920c8 531 }
fahimalavi 30:0f571a4920c8 532 }
fahimalavi 30:0f571a4920c8 533 }
fahimalavi 30:0f571a4920c8 534 t1.stop();
RobMeades 0:7ccf0e7e8a83 535
RobMeades 0:7ccf0e7e8a83 536 UNLOCK();
RobMeades 0:7ccf0e7e8a83 537 return success;
RobMeades 0:7ccf0e7e8a83 538 }
RobMeades 0:7ccf0e7e8a83 539
RobMeades 0:7ccf0e7e8a83 540 /**********************************************************************
RobMeades 0:7ccf0e7e8a83 541 * PROTECTED METHODS: NETWORK INTERFACE and SOCKETS
RobMeades 0:7ccf0e7e8a83 542 **********************************************************************/
RobMeades 0:7ccf0e7e8a83 543
RobMeades 0:7ccf0e7e8a83 544 // Gain access to us.
RobMeades 0:7ccf0e7e8a83 545 NetworkStack *UbloxATCellularInterface::get_stack()
RobMeades 0:7ccf0e7e8a83 546 {
RobMeades 0:7ccf0e7e8a83 547 return this;
RobMeades 0:7ccf0e7e8a83 548 }
RobMeades 0:7ccf0e7e8a83 549
RobMeades 0:7ccf0e7e8a83 550 // Create a socket.
RobMeades 0:7ccf0e7e8a83 551 nsapi_error_t UbloxATCellularInterface::socket_open(nsapi_socket_t *handle,
RobMeades 0:7ccf0e7e8a83 552 nsapi_protocol_t proto)
RobMeades 0:7ccf0e7e8a83 553 {
RobMeades 0:7ccf0e7e8a83 554 nsapi_error_t nsapi_error = NSAPI_ERROR_DEVICE_ERROR;
RobMeades 0:7ccf0e7e8a83 555 int modem_handle;
RobMeades 0:7ccf0e7e8a83 556 SockCtrl *socket;
RobMeades 0:7ccf0e7e8a83 557 LOCK();
RobMeades 0:7ccf0e7e8a83 558
RobMeades 0:7ccf0e7e8a83 559 // Find a free socket
RobMeades 0:7ccf0e7e8a83 560 socket = find_socket();
RobMeades 0:7ccf0e7e8a83 561 tr_debug("socket_open(%d)", proto);
RobMeades 0:7ccf0e7e8a83 562
RobMeades 0:7ccf0e7e8a83 563 if (socket != NULL) {
SanaMasood 21:2a500a881a5a 564 bool success = false;
RobMeades 0:7ccf0e7e8a83 565 if (proto == NSAPI_UDP) {
RobMeades 0:7ccf0e7e8a83 566 success = _at->send("AT+USOCR=17");
RobMeades 0:7ccf0e7e8a83 567 } else if (proto == NSAPI_TCP) {
RobMeades 0:7ccf0e7e8a83 568 success = _at->send("AT+USOCR=6");
RobMeades 0:7ccf0e7e8a83 569 } else {
RobMeades 0:7ccf0e7e8a83 570 nsapi_error = NSAPI_ERROR_UNSUPPORTED;
RobMeades 0:7ccf0e7e8a83 571 }
RobMeades 0:7ccf0e7e8a83 572
RobMeades 0:7ccf0e7e8a83 573 if (success) {
RobMeades 0:7ccf0e7e8a83 574 nsapi_error = NSAPI_ERROR_NO_SOCKET;
RobMeades 0:7ccf0e7e8a83 575 if (_at->recv("+USOCR: %d\n", &modem_handle) && (modem_handle != SOCKET_UNUSED) &&
RobMeades 0:7ccf0e7e8a83 576 _at->recv("OK")) {
RobMeades 0:7ccf0e7e8a83 577 tr_debug("Socket 0x%8x: handle %d was created", (unsigned int) socket, modem_handle);
RobMeades 0:7ccf0e7e8a83 578 clear_socket(socket);
RobMeades 0:7ccf0e7e8a83 579 socket->modem_handle = modem_handle;
RobMeades 0:7ccf0e7e8a83 580 *handle = (nsapi_socket_t) socket;
RobMeades 0:7ccf0e7e8a83 581 nsapi_error = NSAPI_ERROR_OK;
RobMeades 0:7ccf0e7e8a83 582 }
RobMeades 0:7ccf0e7e8a83 583 }
RobMeades 0:7ccf0e7e8a83 584 } else {
RobMeades 0:7ccf0e7e8a83 585 nsapi_error = NSAPI_ERROR_NO_MEMORY;
RobMeades 0:7ccf0e7e8a83 586 }
RobMeades 0:7ccf0e7e8a83 587
RobMeades 0:7ccf0e7e8a83 588 UNLOCK();
RobMeades 0:7ccf0e7e8a83 589 return nsapi_error;
RobMeades 0:7ccf0e7e8a83 590 }
RobMeades 0:7ccf0e7e8a83 591
RobMeades 0:7ccf0e7e8a83 592 // Close a socket.
RobMeades 0:7ccf0e7e8a83 593 nsapi_error_t UbloxATCellularInterface::socket_close(nsapi_socket_t handle)
RobMeades 0:7ccf0e7e8a83 594 {
RobMeades 0:7ccf0e7e8a83 595 nsapi_error_t nsapi_error = NSAPI_ERROR_DEVICE_ERROR;
RobMeades 0:7ccf0e7e8a83 596 SockCtrl *socket = (SockCtrl *) handle;
RobMeades 0:7ccf0e7e8a83 597 LOCK();
RobMeades 0:7ccf0e7e8a83 598
RobMeades 0:7ccf0e7e8a83 599 tr_debug("socket_close(0x%08x)", (unsigned int) handle);
RobMeades 0:7ccf0e7e8a83 600
RobMeades 0:7ccf0e7e8a83 601 MBED_ASSERT (check_socket(socket));
RobMeades 0:7ccf0e7e8a83 602
RobMeades 0:7ccf0e7e8a83 603 if (_at->send("AT+USOCL=%d", socket->modem_handle) &&
RobMeades 0:7ccf0e7e8a83 604 _at->recv("OK")) {
RobMeades 0:7ccf0e7e8a83 605 clear_socket(socket);
RobMeades 0:7ccf0e7e8a83 606 nsapi_error = NSAPI_ERROR_OK;
RobMeades 0:7ccf0e7e8a83 607 }
RobMeades 0:7ccf0e7e8a83 608
RobMeades 0:7ccf0e7e8a83 609 UNLOCK();
RobMeades 0:7ccf0e7e8a83 610 return nsapi_error;
RobMeades 0:7ccf0e7e8a83 611 }
RobMeades 0:7ccf0e7e8a83 612
RobMeades 0:7ccf0e7e8a83 613 // Bind a local port to a socket.
RobMeades 0:7ccf0e7e8a83 614 nsapi_error_t UbloxATCellularInterface::socket_bind(nsapi_socket_t handle,
RobMeades 0:7ccf0e7e8a83 615 const SocketAddress &address)
RobMeades 0:7ccf0e7e8a83 616 {
RobMeades 0:7ccf0e7e8a83 617 nsapi_error_t nsapi_error = NSAPI_ERROR_NO_SOCKET;
RobMeades 0:7ccf0e7e8a83 618 int proto;
RobMeades 0:7ccf0e7e8a83 619 int modem_handle;
RobMeades 0:7ccf0e7e8a83 620 SockCtrl savedSocket;
RobMeades 0:7ccf0e7e8a83 621 SockCtrl *socket = (SockCtrl *) handle;
RobMeades 0:7ccf0e7e8a83 622 LOCK();
RobMeades 0:7ccf0e7e8a83 623
RobMeades 0:7ccf0e7e8a83 624 tr_debug("socket_bind(0x%08x, :%d)", (unsigned int) handle, address.get_port());
RobMeades 0:7ccf0e7e8a83 625
RobMeades 0:7ccf0e7e8a83 626 MBED_ASSERT (check_socket(socket));
RobMeades 0:7ccf0e7e8a83 627
RobMeades 0:7ccf0e7e8a83 628 // Query the socket type
RobMeades 0:7ccf0e7e8a83 629 if (_at->send("AT+USOCTL=%d,0", socket->modem_handle) &&
RobMeades 0:7ccf0e7e8a83 630 _at->recv("+USOCTL: %*d,0,%d\n", &proto) &&
RobMeades 0:7ccf0e7e8a83 631 _at->recv("OK")) {
RobMeades 0:7ccf0e7e8a83 632 savedSocket = *socket;
RobMeades 0:7ccf0e7e8a83 633 nsapi_error = NSAPI_ERROR_DEVICE_ERROR;
RobMeades 0:7ccf0e7e8a83 634 // Now close the socket and re-open it with the binding given
RobMeades 0:7ccf0e7e8a83 635 if (_at->send("AT+USOCL=%d", socket->modem_handle) &&
RobMeades 0:7ccf0e7e8a83 636 _at->recv("OK")) {
RobMeades 0:7ccf0e7e8a83 637 clear_socket(socket);
RobMeades 0:7ccf0e7e8a83 638 nsapi_error = NSAPI_ERROR_CONNECTION_LOST;
RobMeades 0:7ccf0e7e8a83 639 if (_at->send("AT+USOCR=%d,%d", proto, address.get_port()) &&
RobMeades 0:7ccf0e7e8a83 640 _at->recv("+USOCR: %d\n", &modem_handle) && (modem_handle != SOCKET_UNUSED) &&
RobMeades 0:7ccf0e7e8a83 641 _at->recv("OK")) {
RobMeades 0:7ccf0e7e8a83 642 *socket = savedSocket;
RobMeades 0:7ccf0e7e8a83 643 nsapi_error = NSAPI_ERROR_OK;
RobMeades 0:7ccf0e7e8a83 644 }
RobMeades 0:7ccf0e7e8a83 645 }
RobMeades 0:7ccf0e7e8a83 646 }
RobMeades 0:7ccf0e7e8a83 647
RobMeades 0:7ccf0e7e8a83 648 UNLOCK();
RobMeades 0:7ccf0e7e8a83 649 return nsapi_error;
RobMeades 0:7ccf0e7e8a83 650 }
RobMeades 0:7ccf0e7e8a83 651
RobMeades 0:7ccf0e7e8a83 652 // Connect to a socket
RobMeades 0:7ccf0e7e8a83 653 nsapi_error_t UbloxATCellularInterface::socket_connect(nsapi_socket_t handle,
RobMeades 0:7ccf0e7e8a83 654 const SocketAddress &address)
RobMeades 0:7ccf0e7e8a83 655 {
RobMeades 0:7ccf0e7e8a83 656 nsapi_error_t nsapi_error = NSAPI_ERROR_DEVICE_ERROR;
RobMeades 0:7ccf0e7e8a83 657 SockCtrl *socket = (SockCtrl *) handle;
RobMeades 0:7ccf0e7e8a83 658 LOCK();
RobMeades 0:7ccf0e7e8a83 659
RobMeades 0:7ccf0e7e8a83 660 tr_debug("socket_connect(0x%08x, %s(:%d))", (unsigned int) handle,
RobMeades 0:7ccf0e7e8a83 661 address.get_ip_address(), address.get_port());
RobMeades 0:7ccf0e7e8a83 662
RobMeades 0:7ccf0e7e8a83 663 MBED_ASSERT (check_socket(socket));
RobMeades 0:7ccf0e7e8a83 664
RobMeades 0:7ccf0e7e8a83 665 if (_at->send("AT+USOCO=%d,\"%s\",%d", socket->modem_handle,
RobMeades 0:7ccf0e7e8a83 666 address.get_ip_address(), address.get_port()) &&
RobMeades 0:7ccf0e7e8a83 667 _at->recv("OK")) {
RobMeades 0:7ccf0e7e8a83 668 nsapi_error = NSAPI_ERROR_OK;
RobMeades 0:7ccf0e7e8a83 669 }
RobMeades 0:7ccf0e7e8a83 670
RobMeades 0:7ccf0e7e8a83 671 UNLOCK();
RobMeades 0:7ccf0e7e8a83 672 return nsapi_error;
RobMeades 0:7ccf0e7e8a83 673 }
RobMeades 0:7ccf0e7e8a83 674
RobMeades 0:7ccf0e7e8a83 675 // Send to a socket.
RobMeades 0:7ccf0e7e8a83 676 nsapi_size_or_error_t UbloxATCellularInterface::socket_send(nsapi_socket_t handle,
RobMeades 0:7ccf0e7e8a83 677 const void *data,
RobMeades 0:7ccf0e7e8a83 678 nsapi_size_t size)
RobMeades 0:7ccf0e7e8a83 679 {
RobMeades 0:7ccf0e7e8a83 680 nsapi_size_or_error_t nsapi_error_size = NSAPI_ERROR_DEVICE_ERROR;
RobMeades 0:7ccf0e7e8a83 681 bool success = true;
RobMeades 0:7ccf0e7e8a83 682 const char *buf = (const char *) data;
RobMeades 0:7ccf0e7e8a83 683 nsapi_size_t blk = MAX_WRITE_SIZE;
RobMeades 0:7ccf0e7e8a83 684 nsapi_size_t count = size;
RobMeades 0:7ccf0e7e8a83 685 SockCtrl *socket = (SockCtrl *) handle;
RobMeades 0:7ccf0e7e8a83 686
RobMeades 0:7ccf0e7e8a83 687 tr_debug("socket_send(0x%08x, 0x%08x, %d)", (unsigned int) handle, (unsigned int) data, size);
RobMeades 0:7ccf0e7e8a83 688
RobMeades 0:7ccf0e7e8a83 689 MBED_ASSERT (check_socket(socket));
RobMeades 0:7ccf0e7e8a83 690
RobMeades 15:8cc9a80ac0ad 691 if (socket->modem_handle == SOCKET_UNUSED) {
RobMeades 15:8cc9a80ac0ad 692 tr_debug("socket_send: socket closed");
RobMeades 15:8cc9a80ac0ad 693 return NSAPI_ERROR_NO_SOCKET;
RobMeades 15:8cc9a80ac0ad 694 }
RobMeades 15:8cc9a80ac0ad 695
RobMeades 0:7ccf0e7e8a83 696 while ((count > 0) && success) {
RobMeades 0:7ccf0e7e8a83 697 if (count < blk) {
RobMeades 0:7ccf0e7e8a83 698 blk = count;
RobMeades 0:7ccf0e7e8a83 699 }
RobMeades 0:7ccf0e7e8a83 700 LOCK();
RobMeades 0:7ccf0e7e8a83 701
RobMeades 0:7ccf0e7e8a83 702 if (_at->send("AT+USOWR=%d,%d", socket->modem_handle, blk) && _at->recv("@")) {
RobMeades 0:7ccf0e7e8a83 703 wait_ms(50);
RobMeades 0:7ccf0e7e8a83 704 if ((_at->write(buf, blk) < (int) blk) ||
RobMeades 0:7ccf0e7e8a83 705 !_at->recv("OK")) {
RobMeades 0:7ccf0e7e8a83 706 success = false;
RobMeades 0:7ccf0e7e8a83 707 }
RobMeades 0:7ccf0e7e8a83 708 } else {
RobMeades 0:7ccf0e7e8a83 709 success = false;
RobMeades 0:7ccf0e7e8a83 710 }
RobMeades 0:7ccf0e7e8a83 711
RobMeades 0:7ccf0e7e8a83 712 UNLOCK();
RobMeades 0:7ccf0e7e8a83 713 buf += blk;
RobMeades 0:7ccf0e7e8a83 714 count -= blk;
RobMeades 0:7ccf0e7e8a83 715 }
RobMeades 0:7ccf0e7e8a83 716
RobMeades 0:7ccf0e7e8a83 717 if (success) {
RobMeades 0:7ccf0e7e8a83 718 nsapi_error_size = size - count;
RobMeades 0:7ccf0e7e8a83 719 if (_debug_trace_on) {
RobMeades 0:7ccf0e7e8a83 720 tr_debug("socket_send: %d \"%*.*s\"", size, size, size, (char *) data);
RobMeades 0:7ccf0e7e8a83 721 }
RobMeades 0:7ccf0e7e8a83 722 }
RobMeades 0:7ccf0e7e8a83 723
RobMeades 0:7ccf0e7e8a83 724 return nsapi_error_size;
RobMeades 0:7ccf0e7e8a83 725 }
RobMeades 0:7ccf0e7e8a83 726
RobMeades 0:7ccf0e7e8a83 727 // Send to an IP address.
RobMeades 0:7ccf0e7e8a83 728 nsapi_size_or_error_t UbloxATCellularInterface::socket_sendto(nsapi_socket_t handle,
RobMeades 0:7ccf0e7e8a83 729 const SocketAddress &address,
RobMeades 0:7ccf0e7e8a83 730 const void *data,
RobMeades 0:7ccf0e7e8a83 731 nsapi_size_t size)
RobMeades 0:7ccf0e7e8a83 732 {
RobMeades 0:7ccf0e7e8a83 733 nsapi_size_or_error_t nsapi_error_size = NSAPI_ERROR_DEVICE_ERROR;
RobMeades 0:7ccf0e7e8a83 734 bool success = true;
RobMeades 0:7ccf0e7e8a83 735 const char *buf = (const char *) data;
RobMeades 0:7ccf0e7e8a83 736 nsapi_size_t blk = MAX_WRITE_SIZE;
RobMeades 0:7ccf0e7e8a83 737 nsapi_size_t count = size;
RobMeades 0:7ccf0e7e8a83 738 SockCtrl *socket = (SockCtrl *) handle;
RobMeades 0:7ccf0e7e8a83 739
RobMeades 0:7ccf0e7e8a83 740 tr_debug("socket_sendto(0x%8x, %s(:%d), 0x%08x, %d)", (unsigned int) handle,
RobMeades 0:7ccf0e7e8a83 741 address.get_ip_address(), address.get_port(), (unsigned int) data, size);
RobMeades 0:7ccf0e7e8a83 742
RobMeades 0:7ccf0e7e8a83 743 MBED_ASSERT (check_socket(socket));
RobMeades 0:7ccf0e7e8a83 744
RobMeades 0:7ccf0e7e8a83 745 if (size > MAX_WRITE_SIZE) {
RobMeades 0:7ccf0e7e8a83 746 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 747 }
RobMeades 0:7ccf0e7e8a83 748
RobMeades 0:7ccf0e7e8a83 749 while ((count > 0) && success) {
RobMeades 0:7ccf0e7e8a83 750 if (count < blk) {
RobMeades 0:7ccf0e7e8a83 751 blk = count;
RobMeades 0:7ccf0e7e8a83 752 }
RobMeades 0:7ccf0e7e8a83 753 LOCK();
RobMeades 0:7ccf0e7e8a83 754
RobMeades 0:7ccf0e7e8a83 755 if (_at->send("AT+USOST=%d,\"%s\",%d,%d", socket->modem_handle,
RobMeades 0:7ccf0e7e8a83 756 address.get_ip_address(), address.get_port(), blk) &&
RobMeades 0:7ccf0e7e8a83 757 _at->recv("@")) {
RobMeades 0:7ccf0e7e8a83 758 wait_ms(50);
RobMeades 0:7ccf0e7e8a83 759 if ((_at->write(buf, blk) >= (int) blk) &&
RobMeades 0:7ccf0e7e8a83 760 _at->recv("OK")) {
RobMeades 0:7ccf0e7e8a83 761 } else {
RobMeades 0:7ccf0e7e8a83 762 success = false;
RobMeades 0:7ccf0e7e8a83 763 }
RobMeades 0:7ccf0e7e8a83 764 } else {
RobMeades 0:7ccf0e7e8a83 765 success = false;
RobMeades 0:7ccf0e7e8a83 766 }
RobMeades 0:7ccf0e7e8a83 767
RobMeades 0:7ccf0e7e8a83 768 UNLOCK();
RobMeades 0:7ccf0e7e8a83 769 buf += blk;
RobMeades 0:7ccf0e7e8a83 770 count -= blk;
RobMeades 0:7ccf0e7e8a83 771 }
RobMeades 0:7ccf0e7e8a83 772
RobMeades 0:7ccf0e7e8a83 773 if (success) {
RobMeades 0:7ccf0e7e8a83 774 nsapi_error_size = size - count;
RobMeades 0:7ccf0e7e8a83 775 if (_debug_trace_on) {
RobMeades 0:7ccf0e7e8a83 776 tr_debug("socket_sendto: %d \"%*.*s\"", size, size, size, (char *) data);
RobMeades 0:7ccf0e7e8a83 777 }
RobMeades 0:7ccf0e7e8a83 778 }
RobMeades 0:7ccf0e7e8a83 779
RobMeades 0:7ccf0e7e8a83 780 return nsapi_error_size;
RobMeades 0:7ccf0e7e8a83 781 }
RobMeades 0:7ccf0e7e8a83 782
RobMeades 0:7ccf0e7e8a83 783 // Receive from a socket, TCP style.
RobMeades 0:7ccf0e7e8a83 784 nsapi_size_or_error_t UbloxATCellularInterface::socket_recv(nsapi_socket_t handle,
RobMeades 0:7ccf0e7e8a83 785 void *data,
RobMeades 0:7ccf0e7e8a83 786 nsapi_size_t size)
RobMeades 0:7ccf0e7e8a83 787 {
RobMeades 0:7ccf0e7e8a83 788 nsapi_size_or_error_t nsapi_error_size = NSAPI_ERROR_DEVICE_ERROR;
RobMeades 0:7ccf0e7e8a83 789 bool success = true;
RobMeades 0:7ccf0e7e8a83 790 char *buf = (char *) data;
RobMeades 0:7ccf0e7e8a83 791 nsapi_size_t read_blk;
RobMeades 0:7ccf0e7e8a83 792 nsapi_size_t count = 0;
RobMeades 0:7ccf0e7e8a83 793 unsigned int usord_sz;
RobMeades 0:7ccf0e7e8a83 794 int read_sz;
RobMeades 0:7ccf0e7e8a83 795 Timer timer;
RobMeades 0:7ccf0e7e8a83 796 SockCtrl *socket = (SockCtrl *) handle;
SanaMasood 21:2a500a881a5a 797
RobMeades 0:7ccf0e7e8a83 798
RobMeades 0:7ccf0e7e8a83 799 tr_debug("socket_recv(0x%08x, 0x%08x, %d)",
RobMeades 0:7ccf0e7e8a83 800 (unsigned int) handle, (unsigned int) data, size);
RobMeades 0:7ccf0e7e8a83 801
RobMeades 0:7ccf0e7e8a83 802 MBED_ASSERT (check_socket(socket));
RobMeades 0:7ccf0e7e8a83 803
RobMeades 15:8cc9a80ac0ad 804 if (socket->modem_handle == SOCKET_UNUSED) {
RobMeades 15:8cc9a80ac0ad 805 tr_debug("socket_recv: socket closed");
RobMeades 15:8cc9a80ac0ad 806 return NSAPI_ERROR_NO_SOCKET;
RobMeades 15:8cc9a80ac0ad 807 }
RobMeades 15:8cc9a80ac0ad 808
RobMeades 0:7ccf0e7e8a83 809 timer.start();
RobMeades 0:7ccf0e7e8a83 810
RobMeades 0:7ccf0e7e8a83 811 while (success && (size > 0)) {
SanaMasood 21:2a500a881a5a 812 int at_timeout;
RobMeades 0:7ccf0e7e8a83 813 LOCK();
RobMeades 0:7ccf0e7e8a83 814 at_timeout = _at_timeout;
RobMeades 0:7ccf0e7e8a83 815 at_set_timeout(1000);
RobMeades 0:7ccf0e7e8a83 816
RobMeades 0:7ccf0e7e8a83 817 read_blk = MAX_READ_SIZE;
RobMeades 0:7ccf0e7e8a83 818 if (read_blk > size) {
RobMeades 0:7ccf0e7e8a83 819 read_blk = size;
RobMeades 0:7ccf0e7e8a83 820 }
RobMeades 0:7ccf0e7e8a83 821 if (socket->pending > 0) {
RobMeades 0:7ccf0e7e8a83 822 tr_debug("Socket 0x%08x: modem handle %d has %d byte(s) pending",
RobMeades 0:7ccf0e7e8a83 823 (unsigned int) socket, socket->modem_handle, socket->pending);
RobMeades 0:7ccf0e7e8a83 824 _at->debug_on(false); // ABSOLUTELY no time for debug here if you want to
RobMeades 0:7ccf0e7e8a83 825 // be able to read packets of any size without
RobMeades 0:7ccf0e7e8a83 826 // losing characters in UARTSerial
RobMeades 0:7ccf0e7e8a83 827 if (_at->send("AT+USORD=%d,%d", socket->modem_handle, read_blk) &&
RobMeades 0:7ccf0e7e8a83 828 _at->recv("+USORD: %*d,%d,\"", &usord_sz)) {
RobMeades 10:ba18f4418ee8 829 // Must use what +USORD returns here as it may be less or more than we asked for
RobMeades 10:ba18f4418ee8 830 if (usord_sz > socket->pending) {
RobMeades 10:ba18f4418ee8 831 socket->pending = 0;
RobMeades 10:ba18f4418ee8 832 } else {
RobMeades 10:ba18f4418ee8 833 socket->pending -= usord_sz;
RobMeades 10:ba18f4418ee8 834 }
RobMeades 0:7ccf0e7e8a83 835 // Note: insert no debug between _at->recv() and _at->read(), no time...
RobMeades 0:7ccf0e7e8a83 836 if (usord_sz > size) {
RobMeades 0:7ccf0e7e8a83 837 usord_sz = size;
RobMeades 0:7ccf0e7e8a83 838 }
RobMeades 0:7ccf0e7e8a83 839 read_sz = _at->read(buf, usord_sz);
RobMeades 0:7ccf0e7e8a83 840 if (read_sz > 0) {
RobMeades 0:7ccf0e7e8a83 841 tr_debug("...read %d byte(s) from modem handle %d...", read_sz,
RobMeades 0:7ccf0e7e8a83 842 socket->modem_handle);
RobMeades 0:7ccf0e7e8a83 843 if (_debug_trace_on) {
RobMeades 0:7ccf0e7e8a83 844 tr_debug("Read returned %d, |%*.*s|", read_sz, read_sz, read_sz, buf);
RobMeades 0:7ccf0e7e8a83 845 }
RobMeades 0:7ccf0e7e8a83 846 count += read_sz;
RobMeades 0:7ccf0e7e8a83 847 buf += read_sz;
RobMeades 0:7ccf0e7e8a83 848 size -= read_sz;
RobMeades 0:7ccf0e7e8a83 849 } else {
RobMeades 0:7ccf0e7e8a83 850 // read() should not fail
RobMeades 0:7ccf0e7e8a83 851 success = false;
RobMeades 0:7ccf0e7e8a83 852 }
RobMeades 0:7ccf0e7e8a83 853 tr_debug("Socket 0x%08x: modem handle %d now has only %d byte(s) pending",
RobMeades 0:7ccf0e7e8a83 854 (unsigned int) socket, socket->modem_handle, socket->pending);
RobMeades 0:7ccf0e7e8a83 855 // Wait for the "OK" before continuing
RobMeades 0:7ccf0e7e8a83 856 _at->recv("OK");
RobMeades 0:7ccf0e7e8a83 857 } else {
RobMeades 0:7ccf0e7e8a83 858 // Should never fail to do _at->send()/_at->recv()
RobMeades 0:7ccf0e7e8a83 859 success = false;
RobMeades 0:7ccf0e7e8a83 860 }
RobMeades 0:7ccf0e7e8a83 861 _at->debug_on(_debug_trace_on);
RobMeades 0:7ccf0e7e8a83 862 } else if (timer.read_ms() < SOCKET_TIMEOUT) {
RobMeades 0:7ccf0e7e8a83 863 // Wait for URCs
RobMeades 0:7ccf0e7e8a83 864 _at->recv(UNNATURAL_STRING);
RobMeades 0:7ccf0e7e8a83 865 } else {
RobMeades 0:7ccf0e7e8a83 866 if (count == 0) {
RobMeades 0:7ccf0e7e8a83 867 // Timeout with nothing received
RobMeades 0:7ccf0e7e8a83 868 nsapi_error_size = NSAPI_ERROR_WOULD_BLOCK;
RobMeades 0:7ccf0e7e8a83 869 success = false;
RobMeades 0:7ccf0e7e8a83 870 }
RobMeades 0:7ccf0e7e8a83 871 size = 0; // This simply to cause an exit
RobMeades 0:7ccf0e7e8a83 872 }
RobMeades 0:7ccf0e7e8a83 873
RobMeades 0:7ccf0e7e8a83 874 at_set_timeout(at_timeout);
RobMeades 0:7ccf0e7e8a83 875 UNLOCK();
RobMeades 0:7ccf0e7e8a83 876 }
RobMeades 0:7ccf0e7e8a83 877 timer.stop();
RobMeades 0:7ccf0e7e8a83 878
RobMeades 0:7ccf0e7e8a83 879 if (success) {
RobMeades 0:7ccf0e7e8a83 880 nsapi_error_size = count;
RobMeades 0:7ccf0e7e8a83 881 }
RobMeades 0:7ccf0e7e8a83 882
RobMeades 0:7ccf0e7e8a83 883 if (_debug_trace_on) {
RobMeades 0:7ccf0e7e8a83 884 tr_debug("socket_recv: %d \"%*.*s\"", count, count, count, buf - count);
RobMeades 0:7ccf0e7e8a83 885 } else {
RobMeades 0:7ccf0e7e8a83 886 tr_debug("socket_recv: received %d byte(s)", count);
RobMeades 0:7ccf0e7e8a83 887 }
RobMeades 0:7ccf0e7e8a83 888
RobMeades 0:7ccf0e7e8a83 889 return nsapi_error_size;
RobMeades 0:7ccf0e7e8a83 890 }
RobMeades 0:7ccf0e7e8a83 891
RobMeades 0:7ccf0e7e8a83 892 // Receive a packet over a UDP socket.
RobMeades 0:7ccf0e7e8a83 893 nsapi_size_or_error_t UbloxATCellularInterface::socket_recvfrom(nsapi_socket_t handle,
RobMeades 0:7ccf0e7e8a83 894 SocketAddress *address,
RobMeades 0:7ccf0e7e8a83 895 void *data,
RobMeades 0:7ccf0e7e8a83 896 nsapi_size_t size)
RobMeades 0:7ccf0e7e8a83 897 {
RobMeades 0:7ccf0e7e8a83 898 nsapi_size_or_error_t nsapi_error_size = NSAPI_ERROR_DEVICE_ERROR;
RobMeades 0:7ccf0e7e8a83 899 bool success = true;
RobMeades 0:7ccf0e7e8a83 900 char *buf = (char *) data;
RobMeades 0:7ccf0e7e8a83 901 nsapi_size_t read_blk;
RobMeades 0:7ccf0e7e8a83 902 nsapi_size_t count = 0;
RobMeades 0:7ccf0e7e8a83 903 char ipAddress[NSAPI_IP_SIZE];
RobMeades 0:7ccf0e7e8a83 904 int port;
RobMeades 0:7ccf0e7e8a83 905 unsigned int usorf_sz;
RobMeades 0:7ccf0e7e8a83 906 int read_sz;
RobMeades 0:7ccf0e7e8a83 907 Timer timer;
RobMeades 0:7ccf0e7e8a83 908 SockCtrl *socket = (SockCtrl *) handle;
RobMeades 0:7ccf0e7e8a83 909
RobMeades 0:7ccf0e7e8a83 910 tr_debug("socket_recvfrom(0x%08x, 0x%08x, %d)",
RobMeades 0:7ccf0e7e8a83 911 (unsigned int) handle, (unsigned int) data, size);
RobMeades 0:7ccf0e7e8a83 912
RobMeades 0:7ccf0e7e8a83 913 MBED_ASSERT (check_socket(socket));
RobMeades 0:7ccf0e7e8a83 914
RobMeades 0:7ccf0e7e8a83 915 timer.start();
RobMeades 0:7ccf0e7e8a83 916
RobMeades 0:7ccf0e7e8a83 917 while (success && (size > 0)) {
SanaMasood 21:2a500a881a5a 918 int at_timeout;
RobMeades 0:7ccf0e7e8a83 919 LOCK();
RobMeades 0:7ccf0e7e8a83 920 at_timeout = _at_timeout;
RobMeades 0:7ccf0e7e8a83 921 at_set_timeout(1000);
RobMeades 0:7ccf0e7e8a83 922
RobMeades 0:7ccf0e7e8a83 923 read_blk = MAX_READ_SIZE;
RobMeades 0:7ccf0e7e8a83 924 if (read_blk > size) {
RobMeades 0:7ccf0e7e8a83 925 read_blk = size;
RobMeades 0:7ccf0e7e8a83 926 }
RobMeades 0:7ccf0e7e8a83 927 if (socket->pending > 0) {
RobMeades 0:7ccf0e7e8a83 928 tr_debug("Socket 0x%08x: modem handle %d has %d byte(s) pending",
RobMeades 0:7ccf0e7e8a83 929 (unsigned int) socket, socket->modem_handle, socket->pending);
RobMeades 0:7ccf0e7e8a83 930 memset (ipAddress, 0, sizeof (ipAddress)); // Ensure terminator
RobMeades 0:7ccf0e7e8a83 931
RobMeades 0:7ccf0e7e8a83 932 // Note: the maximum length of UDP packet we can receive comes from
RobMeades 0:7ccf0e7e8a83 933 // fitting all of the following into one buffer:
RobMeades 0:7ccf0e7e8a83 934 //
RobMeades 0:7ccf0e7e8a83 935 // +USORF: xx,"max.len.ip.address.ipv4.or.ipv6",yyyyy,wwww,"the_data"\r\n
RobMeades 0:7ccf0e7e8a83 936 //
RobMeades 0:7ccf0e7e8a83 937 // where xx is the handle, max.len.ip.address.ipv4.or.ipv6 is NSAPI_IP_SIZE,
RobMeades 0:7ccf0e7e8a83 938 // yyyyy is the port number (max 65536), wwww is the length of the data and
RobMeades 0:7ccf0e7e8a83 939 // the_data is binary data. I make that 29 + 48 + len(the_data),
RobMeades 0:7ccf0e7e8a83 940 // so the overhead is 77 bytes.
RobMeades 0:7ccf0e7e8a83 941
RobMeades 0:7ccf0e7e8a83 942 _at->debug_on(false); // ABSOLUTELY no time for debug here if you want to
RobMeades 0:7ccf0e7e8a83 943 // be able to read packets of any size without
RobMeades 0:7ccf0e7e8a83 944 // losing characters in UARTSerial
RobMeades 0:7ccf0e7e8a83 945 if (_at->send("AT+USORF=%d,%d", socket->modem_handle, read_blk) &&
RobMeades 0:7ccf0e7e8a83 946 _at->recv("+USORF: %*d,\"%" u_stringify(NSAPI_IP_SIZE) "[^\"]\",%d,%d,\"",
RobMeades 0:7ccf0e7e8a83 947 ipAddress, &port, &usorf_sz)) {
RobMeades 10:ba18f4418ee8 948 // Must use what +USORF returns here as it may be less or more than we asked for
RobMeades 10:ba18f4418ee8 949 if (usorf_sz > socket->pending) {
RobMeades 10:ba18f4418ee8 950 socket->pending = 0;
RobMeades 10:ba18f4418ee8 951 } else {
RobMeades 10:ba18f4418ee8 952 socket->pending -= usorf_sz;
RobMeades 10:ba18f4418ee8 953 }
RobMeades 0:7ccf0e7e8a83 954 // Note: insert no debug between _at->recv() and _at->read(), no time...
RobMeades 0:7ccf0e7e8a83 955 if (usorf_sz > size) {
RobMeades 0:7ccf0e7e8a83 956 usorf_sz = size;
RobMeades 0:7ccf0e7e8a83 957 }
RobMeades 0:7ccf0e7e8a83 958 read_sz = _at->read(buf, usorf_sz);
RobMeades 0:7ccf0e7e8a83 959 if (read_sz > 0) {
RobMeades 0:7ccf0e7e8a83 960 address->set_ip_address(ipAddress);
RobMeades 0:7ccf0e7e8a83 961 address->set_port(port);
RobMeades 0:7ccf0e7e8a83 962 tr_debug("...read %d byte(s) from modem handle %d...", read_sz,
RobMeades 0:7ccf0e7e8a83 963 socket->modem_handle);
RobMeades 0:7ccf0e7e8a83 964 if (_debug_trace_on) {
RobMeades 0:7ccf0e7e8a83 965 tr_debug("Read returned %d, |%*.*s|", read_sz, read_sz, read_sz, buf);
RobMeades 0:7ccf0e7e8a83 966 }
RobMeades 0:7ccf0e7e8a83 967 count += read_sz;
RobMeades 0:7ccf0e7e8a83 968 buf += read_sz;
RobMeades 0:7ccf0e7e8a83 969 size -= read_sz;
RobMeades 0:7ccf0e7e8a83 970 if ((usorf_sz < read_blk) || (usorf_sz == MAX_READ_SIZE)) {
RobMeades 0:7ccf0e7e8a83 971 size = 0; // If we've received less than we asked for, or
RobMeades 0:7ccf0e7e8a83 972 // the max size, then a whole UDP packet has arrived and
RobMeades 0:7ccf0e7e8a83 973 // this means DONE.
RobMeades 0:7ccf0e7e8a83 974 }
RobMeades 0:7ccf0e7e8a83 975 } else {
RobMeades 0:7ccf0e7e8a83 976 // read() should not fail
RobMeades 0:7ccf0e7e8a83 977 success = false;
RobMeades 0:7ccf0e7e8a83 978 }
RobMeades 0:7ccf0e7e8a83 979 tr_debug("Socket 0x%08x: modem handle %d now has only %d byte(s) pending",
RobMeades 0:7ccf0e7e8a83 980 (unsigned int) socket, socket->modem_handle, socket->pending);
RobMeades 0:7ccf0e7e8a83 981 // Wait for the "OK" before continuing
RobMeades 0:7ccf0e7e8a83 982 _at->recv("OK");
RobMeades 0:7ccf0e7e8a83 983 } else {
RobMeades 0:7ccf0e7e8a83 984 // Should never fail to do _at->send()/_at->recv()
RobMeades 0:7ccf0e7e8a83 985 success = false;
RobMeades 0:7ccf0e7e8a83 986 }
RobMeades 0:7ccf0e7e8a83 987 _at->debug_on(_debug_trace_on);
RobMeades 0:7ccf0e7e8a83 988 } else if (timer.read_ms() < SOCKET_TIMEOUT) {
RobMeades 0:7ccf0e7e8a83 989 // Wait for URCs
RobMeades 0:7ccf0e7e8a83 990 _at->recv(UNNATURAL_STRING);
RobMeades 0:7ccf0e7e8a83 991 } else {
RobMeades 0:7ccf0e7e8a83 992 if (count == 0) {
RobMeades 0:7ccf0e7e8a83 993 // Timeout with nothing received
RobMeades 0:7ccf0e7e8a83 994 nsapi_error_size = NSAPI_ERROR_WOULD_BLOCK;
RobMeades 0:7ccf0e7e8a83 995 success = false;
RobMeades 0:7ccf0e7e8a83 996 }
RobMeades 0:7ccf0e7e8a83 997 size = 0; // This simply to cause an exit
RobMeades 0:7ccf0e7e8a83 998 }
RobMeades 0:7ccf0e7e8a83 999
RobMeades 0:7ccf0e7e8a83 1000 at_set_timeout(at_timeout);
RobMeades 0:7ccf0e7e8a83 1001 UNLOCK();
RobMeades 0:7ccf0e7e8a83 1002 }
RobMeades 0:7ccf0e7e8a83 1003 timer.stop();
RobMeades 0:7ccf0e7e8a83 1004
RobMeades 0:7ccf0e7e8a83 1005 if (success) {
RobMeades 0:7ccf0e7e8a83 1006 nsapi_error_size = count;
RobMeades 0:7ccf0e7e8a83 1007 }
RobMeades 0:7ccf0e7e8a83 1008
RobMeades 0:7ccf0e7e8a83 1009 if (_debug_trace_on) {
RobMeades 0:7ccf0e7e8a83 1010 tr_debug("socket_recvfrom: %d \"%*.*s\"", count, count, count, buf - count);
RobMeades 0:7ccf0e7e8a83 1011 } else {
RobMeades 0:7ccf0e7e8a83 1012 tr_debug("socket_recvfrom: received %d byte(s)", count);
RobMeades 0:7ccf0e7e8a83 1013 }
RobMeades 0:7ccf0e7e8a83 1014
RobMeades 0:7ccf0e7e8a83 1015 return nsapi_error_size;
RobMeades 0:7ccf0e7e8a83 1016 }
RobMeades 0:7ccf0e7e8a83 1017
RobMeades 0:7ccf0e7e8a83 1018 // Attach an event callback to a socket, required for asynchronous
RobMeades 0:7ccf0e7e8a83 1019 // data reception
RobMeades 0:7ccf0e7e8a83 1020 void UbloxATCellularInterface::socket_attach(nsapi_socket_t handle,
RobMeades 0:7ccf0e7e8a83 1021 void (*callback)(void *),
RobMeades 0:7ccf0e7e8a83 1022 void *data)
RobMeades 0:7ccf0e7e8a83 1023 {
RobMeades 0:7ccf0e7e8a83 1024 SockCtrl *socket = (SockCtrl *) handle;
RobMeades 0:7ccf0e7e8a83 1025
RobMeades 0:7ccf0e7e8a83 1026 MBED_ASSERT (check_socket(socket));
RobMeades 0:7ccf0e7e8a83 1027
RobMeades 0:7ccf0e7e8a83 1028 socket->callback = callback;
RobMeades 0:7ccf0e7e8a83 1029 socket->data = data;
RobMeades 0:7ccf0e7e8a83 1030 }
RobMeades 0:7ccf0e7e8a83 1031
RobMeades 0:7ccf0e7e8a83 1032 // Unsupported TCP server functions.
RobMeades 0:7ccf0e7e8a83 1033 nsapi_error_t UbloxATCellularInterface::socket_listen(nsapi_socket_t handle,
RobMeades 0:7ccf0e7e8a83 1034 int backlog)
RobMeades 0:7ccf0e7e8a83 1035 {
RobMeades 0:7ccf0e7e8a83 1036 return NSAPI_ERROR_UNSUPPORTED;
RobMeades 0:7ccf0e7e8a83 1037 }
RobMeades 0:7ccf0e7e8a83 1038 nsapi_error_t UbloxATCellularInterface::socket_accept(nsapi_socket_t server,
RobMeades 0:7ccf0e7e8a83 1039 nsapi_socket_t *handle,
RobMeades 0:7ccf0e7e8a83 1040 SocketAddress *address)
RobMeades 0:7ccf0e7e8a83 1041 {
RobMeades 0:7ccf0e7e8a83 1042 return NSAPI_ERROR_UNSUPPORTED;
RobMeades 0:7ccf0e7e8a83 1043 }
RobMeades 0:7ccf0e7e8a83 1044
RobMeades 0:7ccf0e7e8a83 1045 // Unsupported option functions.
RobMeades 0:7ccf0e7e8a83 1046 nsapi_error_t UbloxATCellularInterface::setsockopt(nsapi_socket_t handle,
RobMeades 0:7ccf0e7e8a83 1047 int level, int optname,
RobMeades 0:7ccf0e7e8a83 1048 const void *optval,
RobMeades 0:7ccf0e7e8a83 1049 unsigned optlen)
RobMeades 0:7ccf0e7e8a83 1050 {
RobMeades 0:7ccf0e7e8a83 1051 return NSAPI_ERROR_UNSUPPORTED;
RobMeades 0:7ccf0e7e8a83 1052 }
RobMeades 0:7ccf0e7e8a83 1053 nsapi_error_t UbloxATCellularInterface::getsockopt(nsapi_socket_t handle,
RobMeades 0:7ccf0e7e8a83 1054 int level, int optname,
RobMeades 0:7ccf0e7e8a83 1055 void *optval,
RobMeades 0:7ccf0e7e8a83 1056 unsigned *optlen)
RobMeades 0:7ccf0e7e8a83 1057 {
RobMeades 0:7ccf0e7e8a83 1058 return NSAPI_ERROR_UNSUPPORTED;
RobMeades 0:7ccf0e7e8a83 1059 }
RobMeades 0:7ccf0e7e8a83 1060
RobMeades 0:7ccf0e7e8a83 1061 /**********************************************************************
RobMeades 0:7ccf0e7e8a83 1062 * PUBLIC METHODS
RobMeades 0:7ccf0e7e8a83 1063 **********************************************************************/
RobMeades 0:7ccf0e7e8a83 1064
RobMeades 0:7ccf0e7e8a83 1065 // Constructor.
RobMeades 0:7ccf0e7e8a83 1066 UbloxATCellularInterface::UbloxATCellularInterface(PinName tx,
RobMeades 0:7ccf0e7e8a83 1067 PinName rx,
RobMeades 0:7ccf0e7e8a83 1068 int baud,
amq 16:2b30a056ae54 1069 bool debug_on,
amq 16:2b30a056ae54 1070 osPriority priority)
RobMeades 0:7ccf0e7e8a83 1071 {
RobMeades 0:7ccf0e7e8a83 1072 _sim_pin_check_change_pending = false;
RobMeades 0:7ccf0e7e8a83 1073 _sim_pin_check_change_pending_enabled_value = false;
RobMeades 0:7ccf0e7e8a83 1074 _sim_pin_change_pending = false;
RobMeades 0:7ccf0e7e8a83 1075 _sim_pin_change_pending_new_pin_value = NULL;
RobMeades 14:e7dcf3388403 1076 _run_event_thread = true;
RobMeades 0:7ccf0e7e8a83 1077 _apn = NULL;
RobMeades 0:7ccf0e7e8a83 1078 _uname = NULL;
RobMeades 0:7ccf0e7e8a83 1079 _pwd = NULL;
SanaMasood 21:2a500a881a5a 1080
SanaMasood 21:2a500a881a5a 1081
SanaMasood 21:2a500a881a5a 1082
RobMeades 0:7ccf0e7e8a83 1083
RobMeades 0:7ccf0e7e8a83 1084 // Initialise sockets storage
RobMeades 0:7ccf0e7e8a83 1085 memset(_sockets, 0, sizeof(_sockets));
RobMeades 0:7ccf0e7e8a83 1086 for (unsigned int socket = 0; socket < sizeof(_sockets) / sizeof(_sockets[0]); socket++) {
RobMeades 0:7ccf0e7e8a83 1087 _sockets[socket].modem_handle = SOCKET_UNUSED;
RobMeades 0:7ccf0e7e8a83 1088 _sockets[socket].callback = NULL;
RobMeades 0:7ccf0e7e8a83 1089 _sockets[socket].data = NULL;
RobMeades 0:7ccf0e7e8a83 1090 }
RobMeades 0:7ccf0e7e8a83 1091
RobMeades 0:7ccf0e7e8a83 1092 // The authentication to use
RobMeades 0:7ccf0e7e8a83 1093 _auth = NSAPI_SECURITY_UNKNOWN;
RobMeades 0:7ccf0e7e8a83 1094
RobMeades 0:7ccf0e7e8a83 1095 // Nullify the temporary IP address storage
RobMeades 0:7ccf0e7e8a83 1096 _ip = NULL;
SanaMasood 21:2a500a881a5a 1097 _connection_status_cb = NULL;
SanaMasood 21:2a500a881a5a 1098
RobMeades 0:7ccf0e7e8a83 1099
RobMeades 0:7ccf0e7e8a83 1100 // Initialise the base class, which starts the AT parser
RobMeades 0:7ccf0e7e8a83 1101 baseClassInit(tx, rx, baud, debug_on);
RobMeades 0:7ccf0e7e8a83 1102
RobMeades 0:7ccf0e7e8a83 1103 // Start the event handler thread for Rx data
RobMeades 0:7ccf0e7e8a83 1104 event_thread.start(callback(this, &UbloxATCellularInterface::handle_event));
amq 16:2b30a056ae54 1105 event_thread.set_priority(priority);
RobMeades 0:7ccf0e7e8a83 1106
RobMeades 0:7ccf0e7e8a83 1107 // URC handlers for sockets
RobMeades 0:7ccf0e7e8a83 1108 _at->oob("+UUSORD", callback(this, &UbloxATCellularInterface::UUSORD_URC));
RobMeades 0:7ccf0e7e8a83 1109 _at->oob("+UUSORF", callback(this, &UbloxATCellularInterface::UUSORF_URC));
RobMeades 0:7ccf0e7e8a83 1110 _at->oob("+UUSOCL", callback(this, &UbloxATCellularInterface::UUSOCL_URC));
RobMeades 0:7ccf0e7e8a83 1111 _at->oob("+UUPSDD", callback(this, &UbloxATCellularInterface::UUPSDD_URC));
RobMeades 0:7ccf0e7e8a83 1112 }
RobMeades 0:7ccf0e7e8a83 1113
RobMeades 0:7ccf0e7e8a83 1114 // Destructor.
RobMeades 0:7ccf0e7e8a83 1115 UbloxATCellularInterface::~UbloxATCellularInterface()
RobMeades 0:7ccf0e7e8a83 1116 {
RobMeades 14:e7dcf3388403 1117 // Let the event thread shut down tidily
RobMeades 14:e7dcf3388403 1118 _run_event_thread = false;
RobMeades 14:e7dcf3388403 1119 event_thread.join();
RobMeades 14:e7dcf3388403 1120
RobMeades 0:7ccf0e7e8a83 1121 // Free _ip if it was ever allocated
RobMeades 0:7ccf0e7e8a83 1122 free(_ip);
RobMeades 0:7ccf0e7e8a83 1123 }
RobMeades 0:7ccf0e7e8a83 1124
RobMeades 0:7ccf0e7e8a83 1125 // Set the authentication scheme.
RobMeades 0:7ccf0e7e8a83 1126 void UbloxATCellularInterface::set_authentication(nsapi_security_t auth)
RobMeades 0:7ccf0e7e8a83 1127 {
RobMeades 0:7ccf0e7e8a83 1128 _auth = auth;
RobMeades 0:7ccf0e7e8a83 1129 }
RobMeades 0:7ccf0e7e8a83 1130
RobMeades 0:7ccf0e7e8a83 1131 // Set APN, user name and password.
RobMeades 0:7ccf0e7e8a83 1132 void UbloxATCellularInterface::set_credentials(const char *apn,
RobMeades 0:7ccf0e7e8a83 1133 const char *uname,
RobMeades 0:7ccf0e7e8a83 1134 const char *pwd)
RobMeades 0:7ccf0e7e8a83 1135 {
RobMeades 0:7ccf0e7e8a83 1136 _apn = apn;
RobMeades 0:7ccf0e7e8a83 1137 _uname = uname;
RobMeades 0:7ccf0e7e8a83 1138 _pwd = pwd;
RobMeades 0:7ccf0e7e8a83 1139 }
RobMeades 0:7ccf0e7e8a83 1140
RobMeades 0:7ccf0e7e8a83 1141 // Set PIN.
RobMeades 12:ff6fac481487 1142 void UbloxATCellularInterface::set_sim_pin(const char *pin)
RobMeades 12:ff6fac481487 1143 {
RobMeades 0:7ccf0e7e8a83 1144 set_pin(pin);
RobMeades 0:7ccf0e7e8a83 1145 }
RobMeades 0:7ccf0e7e8a83 1146
RobMeades 0:7ccf0e7e8a83 1147 // Get the IP address of a host.
RobMeades 0:7ccf0e7e8a83 1148 nsapi_error_t UbloxATCellularInterface::gethostbyname(const char *host,
RobMeades 0:7ccf0e7e8a83 1149 SocketAddress *address,
RobMeades 0:7ccf0e7e8a83 1150 nsapi_version_t version)
RobMeades 0:7ccf0e7e8a83 1151 {
RobMeades 0:7ccf0e7e8a83 1152 nsapi_error_t nsapi_error = NSAPI_ERROR_DEVICE_ERROR;
SanaMasood 21:2a500a881a5a 1153
RobMeades 0:7ccf0e7e8a83 1154
RobMeades 0:7ccf0e7e8a83 1155 if (address->set_ip_address(host)) {
RobMeades 0:7ccf0e7e8a83 1156 nsapi_error = NSAPI_ERROR_OK;
RobMeades 0:7ccf0e7e8a83 1157 } else {
SanaMasood 21:2a500a881a5a 1158 int at_timeout;
SanaMasood 21:2a500a881a5a 1159 char ipAddress[NSAPI_IP_SIZE];
RobMeades 0:7ccf0e7e8a83 1160 LOCK();
rob.meades@u-blox.com 6:63dad754c267 1161 // This interrogation can sometimes take longer than the usual 8 seconds
rob.meades@u-blox.com 6:63dad754c267 1162 at_timeout = _at_timeout;
rob.meades@u-blox.com 6:63dad754c267 1163 at_set_timeout(60000);
RobMeades 0:7ccf0e7e8a83 1164 memset (ipAddress, 0, sizeof (ipAddress)); // Ensure terminator
RobMeades 0:7ccf0e7e8a83 1165 if (_at->send("AT+UDNSRN=0,\"%s\"", host) &&
RobMeades 0:7ccf0e7e8a83 1166 _at->recv("+UDNSRN: \"%" u_stringify(NSAPI_IP_SIZE) "[^\"]\"", ipAddress) &&
RobMeades 0:7ccf0e7e8a83 1167 _at->recv("OK")) {
RobMeades 0:7ccf0e7e8a83 1168 if (address->set_ip_address(ipAddress)) {
RobMeades 0:7ccf0e7e8a83 1169 nsapi_error = NSAPI_ERROR_OK;
RobMeades 0:7ccf0e7e8a83 1170 }
RobMeades 0:7ccf0e7e8a83 1171 }
rob.meades@u-blox.com 6:63dad754c267 1172 at_set_timeout(at_timeout);
RobMeades 0:7ccf0e7e8a83 1173 UNLOCK();
RobMeades 0:7ccf0e7e8a83 1174 }
RobMeades 0:7ccf0e7e8a83 1175
RobMeades 0:7ccf0e7e8a83 1176 return nsapi_error;
RobMeades 0:7ccf0e7e8a83 1177 }
RobMeades 0:7ccf0e7e8a83 1178
RobMeades 0:7ccf0e7e8a83 1179 // Make a cellular connection
RobMeades 0:7ccf0e7e8a83 1180 nsapi_error_t UbloxATCellularInterface::connect(const char *sim_pin,
RobMeades 0:7ccf0e7e8a83 1181 const char *apn,
RobMeades 0:7ccf0e7e8a83 1182 const char *uname,
RobMeades 0:7ccf0e7e8a83 1183 const char *pwd)
RobMeades 0:7ccf0e7e8a83 1184 {
RobMeades 0:7ccf0e7e8a83 1185 nsapi_error_t nsapi_error;
RobMeades 0:7ccf0e7e8a83 1186
RobMeades 0:7ccf0e7e8a83 1187 if (sim_pin != NULL) {
RobMeades 0:7ccf0e7e8a83 1188 _pin = sim_pin;
RobMeades 0:7ccf0e7e8a83 1189 }
RobMeades 0:7ccf0e7e8a83 1190
RobMeades 0:7ccf0e7e8a83 1191 if (apn != NULL) {
RobMeades 0:7ccf0e7e8a83 1192 _apn = apn;
RobMeades 0:7ccf0e7e8a83 1193 }
RobMeades 0:7ccf0e7e8a83 1194
RobMeades 0:7ccf0e7e8a83 1195 if ((uname != NULL) && (pwd != NULL)) {
RobMeades 0:7ccf0e7e8a83 1196 _uname = uname;
RobMeades 0:7ccf0e7e8a83 1197 _pwd = pwd;
RobMeades 0:7ccf0e7e8a83 1198 } else {
RobMeades 0:7ccf0e7e8a83 1199 _uname = NULL;
RobMeades 0:7ccf0e7e8a83 1200 _pwd = NULL;
RobMeades 0:7ccf0e7e8a83 1201 }
RobMeades 0:7ccf0e7e8a83 1202
RobMeades 0:7ccf0e7e8a83 1203 nsapi_error = connect();
RobMeades 0:7ccf0e7e8a83 1204
RobMeades 0:7ccf0e7e8a83 1205 return nsapi_error;
RobMeades 0:7ccf0e7e8a83 1206 }
RobMeades 0:7ccf0e7e8a83 1207
RobMeades 0:7ccf0e7e8a83 1208 // Make a cellular connection using the IP stack on board the cellular modem
RobMeades 0:7ccf0e7e8a83 1209 nsapi_error_t UbloxATCellularInterface::connect()
RobMeades 0:7ccf0e7e8a83 1210 {
RobMeades 0:7ccf0e7e8a83 1211 nsapi_error_t nsapi_error = NSAPI_ERROR_DEVICE_ERROR;
RobMeades 0:7ccf0e7e8a83 1212 bool registered = false;
RobMeades 0:7ccf0e7e8a83 1213
RobMeades 0:7ccf0e7e8a83 1214 // Set up modem and then register with the network
RobMeades 0:7ccf0e7e8a83 1215 if (init()) {
RobMeades 0:7ccf0e7e8a83 1216 nsapi_error = NSAPI_ERROR_NO_CONNECTION;
RobMeades 0:7ccf0e7e8a83 1217 // Perform any pending SIM actions
RobMeades 0:7ccf0e7e8a83 1218 if (_sim_pin_check_change_pending) {
RobMeades 0:7ccf0e7e8a83 1219 if (!sim_pin_check_enable(_sim_pin_check_change_pending_enabled_value)) {
RobMeades 0:7ccf0e7e8a83 1220 nsapi_error = NSAPI_ERROR_AUTH_FAILURE;
RobMeades 0:7ccf0e7e8a83 1221 }
RobMeades 0:7ccf0e7e8a83 1222 _sim_pin_check_change_pending = false;
RobMeades 0:7ccf0e7e8a83 1223 }
RobMeades 0:7ccf0e7e8a83 1224 if (_sim_pin_change_pending) {
RobMeades 0:7ccf0e7e8a83 1225 if (!change_sim_pin(_sim_pin_change_pending_new_pin_value)) {
RobMeades 0:7ccf0e7e8a83 1226 nsapi_error = NSAPI_ERROR_AUTH_FAILURE;
RobMeades 0:7ccf0e7e8a83 1227 }
RobMeades 0:7ccf0e7e8a83 1228 _sim_pin_change_pending = false;
RobMeades 0:7ccf0e7e8a83 1229 }
wajahat.abbas@u-blox.com 24:35d5b2a02df8 1230 #ifdef TARGET_UBLOX_C030_R41XM
wajahat.abbas@u-blox.com 24:35d5b2a02df8 1231 define_context();
wajahat.abbas@u-blox.com 24:35d5b2a02df8 1232 #endif
RobMeades 0:7ccf0e7e8a83 1233 if (nsapi_error == NSAPI_ERROR_NO_CONNECTION) {
RobMeades 0:7ccf0e7e8a83 1234 for (int retries = 0; !registered && (retries < 3); retries++) {
RobMeades 0:7ccf0e7e8a83 1235 if (nwk_registration()) {
wajahat.abbas@u-blox.com 24:35d5b2a02df8 1236 registered = true;
wajahat.abbas@u-blox.com 24:35d5b2a02df8 1237 #ifdef TARGET_UBLOX_C030_R41XM
wajahat.abbas@u-blox.com 34:ca02f8448085 1238 if (is_context_active()) {
fahimalavi 29:773cfb0fe56c 1239 nsapi_error = NSAPI_ERROR_OK;
wajahat.abbas@u-blox.com 34:ca02f8448085 1240 tr_info("Context is already active\r\n");
wajahat.abbas@u-blox.com 34:ca02f8448085 1241 } else {
wajahat.abbas@u-blox.com 34:ca02f8448085 1242 tr_info("Context is not active, activating it.\r\n");
wajahat.abbas@u-blox.com 34:ca02f8448085 1243 if (activate_context()) {
wajahat.abbas@u-blox.com 34:ca02f8448085 1244 nsapi_error = NSAPI_ERROR_OK;
wajahat.abbas@u-blox.com 34:ca02f8448085 1245 }
wajahat.abbas@u-blox.com 24:35d5b2a02df8 1246 }
wajahat.abbas@u-blox.com 24:35d5b2a02df8 1247 #endif
RobMeades 0:7ccf0e7e8a83 1248 }
RobMeades 0:7ccf0e7e8a83 1249 }
RobMeades 0:7ccf0e7e8a83 1250 }
RobMeades 0:7ccf0e7e8a83 1251 }
wajahat.abbas@u-blox.com 24:35d5b2a02df8 1252 #ifndef TARGET_UBLOX_C030_R41XM
RobMeades 0:7ccf0e7e8a83 1253 // Attempt to establish a connection
RobMeades 0:7ccf0e7e8a83 1254 if (registered && connect_modem_stack()) {
RobMeades 0:7ccf0e7e8a83 1255 nsapi_error = NSAPI_ERROR_OK;
RobMeades 0:7ccf0e7e8a83 1256 }
wajahat.abbas@u-blox.com 24:35d5b2a02df8 1257 #endif
RobMeades 0:7ccf0e7e8a83 1258 return nsapi_error;
RobMeades 0:7ccf0e7e8a83 1259 }
RobMeades 0:7ccf0e7e8a83 1260
RobMeades 0:7ccf0e7e8a83 1261 // User initiated disconnect.
RobMeades 0:7ccf0e7e8a83 1262 nsapi_error_t UbloxATCellularInterface::disconnect()
RobMeades 0:7ccf0e7e8a83 1263 {
RobMeades 0:7ccf0e7e8a83 1264 nsapi_error_t nsapi_error = NSAPI_ERROR_DEVICE_ERROR;
fahim.alavi@u-blox.com 19:7013521e75e7 1265 #ifdef TARGET_UBLOX_C030_R41XM
fahim.alavi@u-blox.com 19:7013521e75e7 1266 if (nwk_deregistration()) {
wajahat.abbas@u-blox.com 26:4f28a1eaa2aa 1267 if (_connection_status_cb) {
wajahat.abbas@u-blox.com 26:4f28a1eaa2aa 1268 _connection_status_cb(NSAPI_ERROR_CONNECTION_LOST);
wajahat.abbas@u-blox.com 26:4f28a1eaa2aa 1269 }
fahim.alavi@u-blox.com 19:7013521e75e7 1270 #else
RobMeades 0:7ccf0e7e8a83 1271 if (disconnect_modem_stack() && nwk_deregistration()) {
fahim.alavi@u-blox.com 19:7013521e75e7 1272 #endif
RobMeades 0:7ccf0e7e8a83 1273 nsapi_error = NSAPI_ERROR_OK;
RobMeades 0:7ccf0e7e8a83 1274 }
RobMeades 0:7ccf0e7e8a83 1275
RobMeades 0:7ccf0e7e8a83 1276 return nsapi_error;
RobMeades 0:7ccf0e7e8a83 1277 }
RobMeades 0:7ccf0e7e8a83 1278
RobMeades 0:7ccf0e7e8a83 1279 // Enable or disable SIM PIN check lock.
RobMeades 0:7ccf0e7e8a83 1280 nsapi_error_t UbloxATCellularInterface::set_sim_pin_check(bool set,
RobMeades 0:7ccf0e7e8a83 1281 bool immediate,
RobMeades 0:7ccf0e7e8a83 1282 const char *sim_pin)
RobMeades 0:7ccf0e7e8a83 1283 {
RobMeades 0:7ccf0e7e8a83 1284 nsapi_error_t nsapi_error = NSAPI_ERROR_AUTH_FAILURE;
RobMeades 0:7ccf0e7e8a83 1285
RobMeades 0:7ccf0e7e8a83 1286 if (sim_pin != NULL) {
RobMeades 0:7ccf0e7e8a83 1287 _pin = sim_pin;
RobMeades 0:7ccf0e7e8a83 1288 }
RobMeades 0:7ccf0e7e8a83 1289
RobMeades 0:7ccf0e7e8a83 1290 if (immediate) {
RobMeades 0:7ccf0e7e8a83 1291 if (init()) {
RobMeades 0:7ccf0e7e8a83 1292 if (sim_pin_check_enable(set)) {
RobMeades 0:7ccf0e7e8a83 1293 nsapi_error = NSAPI_ERROR_OK;
RobMeades 0:7ccf0e7e8a83 1294 }
RobMeades 0:7ccf0e7e8a83 1295 } else {
RobMeades 0:7ccf0e7e8a83 1296 nsapi_error = NSAPI_ERROR_DEVICE_ERROR;
RobMeades 0:7ccf0e7e8a83 1297 }
RobMeades 0:7ccf0e7e8a83 1298 } else {
RobMeades 0:7ccf0e7e8a83 1299 nsapi_error = NSAPI_ERROR_OK;
RobMeades 0:7ccf0e7e8a83 1300 _sim_pin_check_change_pending = true;
RobMeades 0:7ccf0e7e8a83 1301 _sim_pin_check_change_pending_enabled_value = set;
RobMeades 0:7ccf0e7e8a83 1302 }
RobMeades 0:7ccf0e7e8a83 1303
RobMeades 0:7ccf0e7e8a83 1304 return nsapi_error;
RobMeades 0:7ccf0e7e8a83 1305 }
RobMeades 0:7ccf0e7e8a83 1306
RobMeades 0:7ccf0e7e8a83 1307 // Change the PIN code for the SIM card.
RobMeades 0:7ccf0e7e8a83 1308 nsapi_error_t UbloxATCellularInterface::set_new_sim_pin(const char *new_pin,
RobMeades 0:7ccf0e7e8a83 1309 bool immediate,
RobMeades 0:7ccf0e7e8a83 1310 const char *old_pin)
RobMeades 0:7ccf0e7e8a83 1311 {
RobMeades 0:7ccf0e7e8a83 1312 nsapi_error_t nsapi_error = NSAPI_ERROR_AUTH_FAILURE;
RobMeades 0:7ccf0e7e8a83 1313
RobMeades 0:7ccf0e7e8a83 1314 if (old_pin != NULL) {
RobMeades 0:7ccf0e7e8a83 1315 _pin = old_pin;
RobMeades 0:7ccf0e7e8a83 1316 }
RobMeades 0:7ccf0e7e8a83 1317
RobMeades 0:7ccf0e7e8a83 1318 if (immediate) {
RobMeades 0:7ccf0e7e8a83 1319 if (init()) {
RobMeades 0:7ccf0e7e8a83 1320 if (change_sim_pin(new_pin)) {
RobMeades 0:7ccf0e7e8a83 1321 nsapi_error = NSAPI_ERROR_OK;
RobMeades 0:7ccf0e7e8a83 1322 }
RobMeades 0:7ccf0e7e8a83 1323 } else {
RobMeades 0:7ccf0e7e8a83 1324 nsapi_error = NSAPI_ERROR_DEVICE_ERROR;
RobMeades 0:7ccf0e7e8a83 1325 }
RobMeades 0:7ccf0e7e8a83 1326 } else {
RobMeades 0:7ccf0e7e8a83 1327 nsapi_error = NSAPI_ERROR_OK;
RobMeades 0:7ccf0e7e8a83 1328 _sim_pin_change_pending = true;
RobMeades 0:7ccf0e7e8a83 1329 _sim_pin_change_pending_new_pin_value = new_pin;
RobMeades 0:7ccf0e7e8a83 1330 }
RobMeades 0:7ccf0e7e8a83 1331
RobMeades 0:7ccf0e7e8a83 1332 return nsapi_error;
RobMeades 0:7ccf0e7e8a83 1333 }
RobMeades 0:7ccf0e7e8a83 1334
RobMeades 0:7ccf0e7e8a83 1335 // Determine if the connection is up.
RobMeades 0:7ccf0e7e8a83 1336 bool UbloxATCellularInterface::is_connected()
RobMeades 0:7ccf0e7e8a83 1337 {
RobMeades 0:7ccf0e7e8a83 1338 return get_ip_address() != NULL;
RobMeades 0:7ccf0e7e8a83 1339 }
RobMeades 0:7ccf0e7e8a83 1340
RobMeades 0:7ccf0e7e8a83 1341 // Get the IP address of the on-board modem IP stack.
RobMeades 0:7ccf0e7e8a83 1342 const char * UbloxATCellularInterface::get_ip_address()
RobMeades 0:7ccf0e7e8a83 1343 {
RobMeades 0:7ccf0e7e8a83 1344 SocketAddress address;
RobMeades 0:7ccf0e7e8a83 1345 LOCK();
RobMeades 0:7ccf0e7e8a83 1346
RobMeades 0:7ccf0e7e8a83 1347 if (_ip == NULL) {
RobMeades 0:7ccf0e7e8a83 1348 // Temporary storage for an IP address string with terminator
RobMeades 0:7ccf0e7e8a83 1349 _ip = (char *) malloc(NSAPI_IP_SIZE);
RobMeades 0:7ccf0e7e8a83 1350 }
RobMeades 0:7ccf0e7e8a83 1351
RobMeades 0:7ccf0e7e8a83 1352 if (_ip != NULL) {
RobMeades 0:7ccf0e7e8a83 1353 memset(_ip, 0, NSAPI_IP_SIZE); // Ensure a terminator
RobMeades 0:7ccf0e7e8a83 1354 // +UPSND=<profile_id>,<param_tag>[,<dynamic_param_val>]
RobMeades 0:7ccf0e7e8a83 1355 // If we get back a quoted "w.x.y.z" then we have an IP address,
RobMeades 0:7ccf0e7e8a83 1356 // otherwise we don't.
wajahat.abbas@u-blox.com 26:4f28a1eaa2aa 1357 #ifdef TARGET_UBLOX_C030_R41XM
wajahat.abbas@u-blox.com 26:4f28a1eaa2aa 1358 if (!_at->send("AT+CGPADDR=1") ||
wajahat.abbas@u-blox.com 26:4f28a1eaa2aa 1359 !_at->recv("+CGPADDR: 1,%" u_stringify(NSAPI_IP_SIZE) "[^\n]\nOK\n", _ip) ||
wajahat.abbas@u-blox.com 26:4f28a1eaa2aa 1360 !address.set_ip_address(_ip) || // Return NULL if the address is not a valid one
wajahat.abbas@u-blox.com 26:4f28a1eaa2aa 1361 !address) { // Return null if the address is zero
wajahat.abbas@u-blox.com 26:4f28a1eaa2aa 1362 free (_ip);
wajahat.abbas@u-blox.com 26:4f28a1eaa2aa 1363 _ip = NULL;
wajahat.abbas@u-blox.com 26:4f28a1eaa2aa 1364 }
wajahat.abbas@u-blox.com 26:4f28a1eaa2aa 1365 #else
RobMeades 0:7ccf0e7e8a83 1366 if (!_at->send("AT+UPSND=" PROFILE ",0") ||
RobMeades 0:7ccf0e7e8a83 1367 !_at->recv("+UPSND: " PROFILE ",0,\"%" u_stringify(NSAPI_IP_SIZE) "[^\"]\"", _ip) ||
RobMeades 0:7ccf0e7e8a83 1368 !_at->recv("OK") ||
RobMeades 0:7ccf0e7e8a83 1369 !address.set_ip_address(_ip) || // Return NULL if the address is not a valid one
RobMeades 0:7ccf0e7e8a83 1370 !address) { // Return null if the address is zero
RobMeades 0:7ccf0e7e8a83 1371 free (_ip);
RobMeades 0:7ccf0e7e8a83 1372 _ip = NULL;
RobMeades 0:7ccf0e7e8a83 1373 }
wajahat.abbas@u-blox.com 26:4f28a1eaa2aa 1374 #endif
RobMeades 0:7ccf0e7e8a83 1375 }
RobMeades 0:7ccf0e7e8a83 1376
RobMeades 0:7ccf0e7e8a83 1377 UNLOCK();
RobMeades 0:7ccf0e7e8a83 1378 return _ip;
RobMeades 0:7ccf0e7e8a83 1379 }
RobMeades 0:7ccf0e7e8a83 1380
RobMeades 0:7ccf0e7e8a83 1381 // Get the local network mask.
RobMeades 0:7ccf0e7e8a83 1382 const char *UbloxATCellularInterface::get_netmask()
RobMeades 0:7ccf0e7e8a83 1383 {
RobMeades 0:7ccf0e7e8a83 1384 // Not implemented.
RobMeades 0:7ccf0e7e8a83 1385 return NULL;
RobMeades 0:7ccf0e7e8a83 1386 }
RobMeades 0:7ccf0e7e8a83 1387
RobMeades 0:7ccf0e7e8a83 1388 // Get the local gateways.
RobMeades 0:7ccf0e7e8a83 1389 const char *UbloxATCellularInterface::get_gateway()
RobMeades 0:7ccf0e7e8a83 1390 {
RobMeades 0:7ccf0e7e8a83 1391 return get_ip_address();
RobMeades 0:7ccf0e7e8a83 1392 }
RobMeades 0:7ccf0e7e8a83 1393
RobMeades 0:7ccf0e7e8a83 1394 // Callback in case the connection is lost.
RobMeades 0:7ccf0e7e8a83 1395 void UbloxATCellularInterface::connection_status_cb(Callback<void(nsapi_error_t)> cb)
RobMeades 0:7ccf0e7e8a83 1396 {
RobMeades 0:7ccf0e7e8a83 1397 _connection_status_cb = cb;
RobMeades 0:7ccf0e7e8a83 1398 }
RobMeades 0:7ccf0e7e8a83 1399
fahim.alavi@u-blox.com 17:7b033423126c 1400 void UbloxATCellularInterface::set_plmn(const char *plmn) {
fahim.alavi@u-blox.com 17:7b033423126c 1401
fahim.alavi@u-blox.com 17:7b033423126c 1402 }
fahim.alavi@u-blox.com 17:7b033423126c 1403
RobMeades 0:7ccf0e7e8a83 1404 // End of file
RobMeades 0:7ccf0e7e8a83 1405