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:
mudassar0121
Date:
Fri Aug 02 11:32:14 2019 +0500
Branch:
profile_polling
Revision:
31:07c9c5c3fb88
Parent:
30:0f571a4920c8
Child:
33:5d5ce25405d4
Polling to check profile activation

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