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

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

Committer:
wajahat.abbas@u-blox.com
Date:
Fri Apr 19 15:40:46 2019 +0500
Revision:
24:35d5b2a02df8
Parent:
19:7013521e75e7
Child:
25:aabc50bc418e
define and activate context in case of R412M

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