GNSS

Dependents:   ublox-at-cellular-interface-ext

Fork of ublox-at-cellular-interface by u-blox

Committer:
fahim.alavi@u-blox.com
Date:
Mon Feb 18 11:42:35 2019 +0500
Revision:
24:c6592eec499a
Parent:
17:b43a3b85353f
Parent:
11:cc41a8636f7e
Child:
25:34c79d68667e
Merging

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