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:
Thu Aug 01 18:06:44 2019 +0500
Revision:
30:0f571a4920c8
Parent:
29:773cfb0fe56c
Child:
31:07c9c5c3fb88
edrx test case added and UPSND support added in disconnect modem stack

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