Mbed Cloud example program for workshop in W27 2018.

Dependencies:   MMA7660 LM75B

Committer:
MACRUM
Date:
Sat Jun 30 01:40:30 2018 +0000
Revision:
0:119624335925
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
MACRUM 0:119624335925 1 /* SPWFSAxx Devices
MACRUM 0:119624335925 2 * Copyright (c) 2015 ARM Limited
MACRUM 0:119624335925 3 *
MACRUM 0:119624335925 4 * Licensed under the Apache License, Version 2.0 (the "License");
MACRUM 0:119624335925 5 * you may not use this file except in compliance with the License.
MACRUM 0:119624335925 6 * You may obtain a copy of the License at
MACRUM 0:119624335925 7 *
MACRUM 0:119624335925 8 * http://www.apache.org/licenses/LICENSE-2.0
MACRUM 0:119624335925 9 *
MACRUM 0:119624335925 10 * Unless required by applicable law or agreed to in writing, software
MACRUM 0:119624335925 11 * distributed under the License is distributed on an "AS IS" BASIS,
MACRUM 0:119624335925 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
MACRUM 0:119624335925 13 * See the License for the specific language governing permissions and
MACRUM 0:119624335925 14 * limitations under the License.
MACRUM 0:119624335925 15 */
MACRUM 0:119624335925 16
MACRUM 0:119624335925 17 #include "mbed_debug.h"
MACRUM 0:119624335925 18
MACRUM 0:119624335925 19 #include "SpwfSAInterface.h" /* must be included first */
MACRUM 0:119624335925 20 #include "SPWFSAxx.h"
MACRUM 0:119624335925 21
MACRUM 0:119624335925 22 static const char out_delim[] = {SPWFSAxx::_cr_, '\0'};
MACRUM 0:119624335925 23
MACRUM 0:119624335925 24 SPWFSAxx::SPWFSAxx(PinName tx, PinName rx,
MACRUM 0:119624335925 25 PinName rts, PinName cts,
MACRUM 0:119624335925 26 SpwfSAInterface &ifce, bool debug,
MACRUM 0:119624335925 27 PinName wakeup, PinName reset)
MACRUM 0:119624335925 28 : _serial(tx, rx, SPWFXX_DEFAULT_BAUD_RATE), _parser(&_serial, out_delim),
MACRUM 0:119624335925 29 _wakeup(wakeup, 1), _reset(reset, 1),
MACRUM 0:119624335925 30 _rts(rts), _cts(cts),
MACRUM 0:119624335925 31 _timeout(SPWF_INIT_TIMEOUT), _dbg_on(debug),
MACRUM 0:119624335925 32 _pending_sockets_bitmap(0),
MACRUM 0:119624335925 33 _network_lost_flag(false),
MACRUM 0:119624335925 34 _associated_interface(ifce),
MACRUM 0:119624335925 35 _call_event_callback_blocked(0),
MACRUM 0:119624335925 36 _callback_func(),
MACRUM 0:119624335925 37 _packets(0), _packets_end(&_packets)
MACRUM 0:119624335925 38 {
MACRUM 0:119624335925 39 memset(_pending_pkt_sizes, 0, sizeof(_pending_pkt_sizes));
MACRUM 0:119624335925 40
MACRUM 0:119624335925 41 _serial.sigio(Callback<void()>(this, &SPWFSAxx::_event_handler));
MACRUM 0:119624335925 42 _parser.debug_on(debug);
MACRUM 0:119624335925 43 _parser.set_timeout(_timeout);
MACRUM 0:119624335925 44
MACRUM 0:119624335925 45 /* unlikely OOBs */
MACRUM 0:119624335925 46 _parser.oob("+WIND:5:WiFi Hardware Failure", callback(this, &SPWFSAxx::_wifi_hwfault_handler));
MACRUM 0:119624335925 47 _parser.oob("+WIND:33:WiFi Network Lost", callback(this, &SPWFSAxx::_network_lost_handler_th));
MACRUM 0:119624335925 48 #if MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1
MACRUM 0:119624335925 49 _parser.oob("+WIND:24:WiFi Up::", callback(this, &SPWFSAxx::_skip_oob));
MACRUM 0:119624335925 50 #endif
MACRUM 0:119624335925 51 _parser.oob("+WIND:8:Hard Fault", callback(this, &SPWFSAxx::_hard_fault_handler));
MACRUM 0:119624335925 52
MACRUM 0:119624335925 53 /* most likely OOBs */
MACRUM 0:119624335925 54 _parser.oob(SPWFXX_OOB_ERROR, callback(this, &SPWFSAxx::_error_handler));
MACRUM 0:119624335925 55 _parser.oob("+WIND:58:Socket Closed", callback(this, &SPWFSAxx::_server_gone_handler));
MACRUM 0:119624335925 56 _parser.oob("+WIND:55:Pending Data", callback(this, &SPWFSAxx::_packet_handler_th));
MACRUM 0:119624335925 57 }
MACRUM 0:119624335925 58
MACRUM 0:119624335925 59 bool SPWFSAxx::startup(int mode)
MACRUM 0:119624335925 60 {
MACRUM 0:119624335925 61 BlockExecuter netsock_wa_obj(Callback<void()>(this, &SPWFSAxx::_unblock_event_callback),
MACRUM 0:119624335925 62 Callback<void()>(this, &SPWFSAxx::_block_event_callback)); /* disable calling (external) callback in IRQ context */
MACRUM 0:119624335925 63
MACRUM 0:119624335925 64 /*Reset module*/
MACRUM 0:119624335925 65 if(!hw_reset()) {
MACRUM 0:119624335925 66 debug_if(_dbg_on, "\r\nSPWF> HW reset failed\r\n");
MACRUM 0:119624335925 67 return false;
MACRUM 0:119624335925 68 }
MACRUM 0:119624335925 69
MACRUM 0:119624335925 70 /* factory reset */
MACRUM 0:119624335925 71 if(!(_parser.send(SPWFXX_SEND_FWCFG) && _recv_ok()))
MACRUM 0:119624335925 72 {
MACRUM 0:119624335925 73 debug_if(_dbg_on, "\r\nSPWF> error restore factory default settings\r\n");
MACRUM 0:119624335925 74 return false;
MACRUM 0:119624335925 75 }
MACRUM 0:119624335925 76
MACRUM 0:119624335925 77 /*switch off led*/
MACRUM 0:119624335925 78 if(!(_parser.send("AT+S.SCFG=blink_led,0") && _recv_ok()))
MACRUM 0:119624335925 79 {
MACRUM 0:119624335925 80 debug_if(_dbg_on, "\r\nSPWF> error stop blinking led (%d)\r\n", __LINE__);
MACRUM 0:119624335925 81 return false;
MACRUM 0:119624335925 82 }
MACRUM 0:119624335925 83
MACRUM 0:119624335925 84 /*set local echo to 0*/
MACRUM 0:119624335925 85 if(!(_parser.send(SPWFXX_SEND_DISABLE_LE) && _recv_ok()))
MACRUM 0:119624335925 86 {
MACRUM 0:119624335925 87 debug_if(_dbg_on, "\r\nSPWF> error local echo set\r\n");
MACRUM 0:119624335925 88 return false;
MACRUM 0:119624335925 89 }
MACRUM 0:119624335925 90
MACRUM 0:119624335925 91 /*set the operational rates*/
MACRUM 0:119624335925 92 if(!(_parser.send("AT+S.SCFG=wifi_opr_rate_mask,0x003FFFCF") && _recv_ok()))
MACRUM 0:119624335925 93 {
MACRUM 0:119624335925 94 debug_if(_dbg_on, "\r\nSPWF> error setting ht_mode\r\n");
MACRUM 0:119624335925 95 return false;
MACRUM 0:119624335925 96 }
MACRUM 0:119624335925 97
MACRUM 0:119624335925 98 /*enable the 802.11n mode*/
MACRUM 0:119624335925 99 if(!(_parser.send("AT+S.SCFG=wifi_ht_mode,1") && _recv_ok()))
MACRUM 0:119624335925 100 {
MACRUM 0:119624335925 101 debug_if(_dbg_on, "\r\nSPWF> error setting operational rates\r\n");
MACRUM 0:119624335925 102 return false;
MACRUM 0:119624335925 103 }
MACRUM 0:119624335925 104
MACRUM 0:119624335925 105 /*set idle mode (0->idle, 1->STA,3->miniAP, 2->IBSS)*/
MACRUM 0:119624335925 106 if(!(_parser.send("AT+S.SCFG=wifi_mode,%d", mode) && _recv_ok()))
MACRUM 0:119624335925 107 {
MACRUM 0:119624335925 108 debug_if(_dbg_on, "\r\nSPWF> error WiFi mode set idle (%d)\r\n", __LINE__);
MACRUM 0:119624335925 109 return false;
MACRUM 0:119624335925 110 }
MACRUM 0:119624335925 111
MACRUM 0:119624335925 112 #if defined(MBED_MAJOR_VERSION)
MACRUM 0:119624335925 113 #if !DEVICE_SERIAL_FC || (MBED_VERSION < MBED_ENCODE_VERSION(5, 7, 0))
MACRUM 0:119624335925 114 /*disable HW flow control*/
MACRUM 0:119624335925 115 if(!(_parser.send(SPWFXX_SEND_DISABLE_FC) && _recv_ok()))
MACRUM 0:119624335925 116 {
MACRUM 0:119624335925 117 debug_if(_dbg_on, "\r\nSPWF> error disabling HW flow control\r\n");
MACRUM 0:119624335925 118 return false;
MACRUM 0:119624335925 119 }
MACRUM 0:119624335925 120 #else // DEVICE_SERIAL_FC && (MBED_VERSION >= MBED_ENCODE_VERSION(5, 7, 0))
MACRUM 0:119624335925 121 if((_rts != NC) && (_cts != NC)) {
MACRUM 0:119624335925 122 /*enable HW flow control*/
MACRUM 0:119624335925 123 if(!(_parser.send(SPWFXX_SEND_ENABLE_FC) && _recv_ok()))
MACRUM 0:119624335925 124 {
MACRUM 0:119624335925 125 debug_if(_dbg_on, "\r\nSPWF> error enabling HW flow control\r\n");
MACRUM 0:119624335925 126 return false;
MACRUM 0:119624335925 127 }
MACRUM 0:119624335925 128
MACRUM 0:119624335925 129 /*configure pins for HW flow control*/
MACRUM 0:119624335925 130 _serial.set_flow_control(SerialBase::RTSCTS, _rts, _cts);
MACRUM 0:119624335925 131 } else {
MACRUM 0:119624335925 132 /*disable HW flow control*/
MACRUM 0:119624335925 133 if(!(_parser.send(SPWFXX_SEND_DISABLE_FC) && _recv_ok()))
MACRUM 0:119624335925 134 {
MACRUM 0:119624335925 135 debug_if(_dbg_on, "\r\nSPWF> error disabling HW flow control\r\n");
MACRUM 0:119624335925 136 return false;
MACRUM 0:119624335925 137 }
MACRUM 0:119624335925 138 }
MACRUM 0:119624335925 139 #endif // DEVICE_SERIAL_FC && (MBED_VERSION >= MBED_ENCODE_VERSION(5, 7, 0))
MACRUM 0:119624335925 140 #else // !defined(MBED_MAJOR_VERSION) - Assuming `master` branch
MACRUM 0:119624335925 141 #if !DEVICE_SERIAL_FC
MACRUM 0:119624335925 142 /*disable HW flow control*/
MACRUM 0:119624335925 143 if(!(_parser.send(SPWFXX_SEND_DISABLE_FC) && _recv_ok()))
MACRUM 0:119624335925 144 {
MACRUM 0:119624335925 145 debug_if(_dbg_on, "\r\nSPWF> error disabling HW flow control\r\n");
MACRUM 0:119624335925 146 return false;
MACRUM 0:119624335925 147 }
MACRUM 0:119624335925 148 #else // DEVICE_SERIAL_FC
MACRUM 0:119624335925 149 if((_rts != NC) && (_cts != NC)) {
MACRUM 0:119624335925 150 /*enable HW flow control*/
MACRUM 0:119624335925 151 if(!(_parser.send(SPWFXX_SEND_ENABLE_FC) && _recv_ok()))
MACRUM 0:119624335925 152 {
MACRUM 0:119624335925 153 debug_if(_dbg_on, "\r\nSPWF> error enabling HW flow control\r\n");
MACRUM 0:119624335925 154 return false;
MACRUM 0:119624335925 155 }
MACRUM 0:119624335925 156
MACRUM 0:119624335925 157 /*configure pins for HW flow control*/
MACRUM 0:119624335925 158 _serial.set_flow_control(SerialBase::RTSCTS, _rts, _cts);
MACRUM 0:119624335925 159 } else {
MACRUM 0:119624335925 160 /*disable HW flow control*/
MACRUM 0:119624335925 161 if(!(_parser.send(SPWFXX_SEND_DISABLE_FC) && _recv_ok()))
MACRUM 0:119624335925 162 {
MACRUM 0:119624335925 163 debug_if(_dbg_on, "\r\nSPWF> error disabling HW flow control\r\n");
MACRUM 0:119624335925 164 return false;
MACRUM 0:119624335925 165 }
MACRUM 0:119624335925 166 }
MACRUM 0:119624335925 167 #endif // DEVICE_SERIAL_FC
MACRUM 0:119624335925 168 #endif // !defined(MBED_MAJOR_VERSION)
MACRUM 0:119624335925 169
MACRUM 0:119624335925 170 /* Disable selected WINDs */
MACRUM 0:119624335925 171 _winds_on();
MACRUM 0:119624335925 172
MACRUM 0:119624335925 173 /* sw reset */
MACRUM 0:119624335925 174 if(!reset()) {
MACRUM 0:119624335925 175 debug_if(_dbg_on, "\r\nSPWF> SW reset failed (%s, %d)\r\n", __func__, __LINE__);
MACRUM 0:119624335925 176 return false;
MACRUM 0:119624335925 177 }
MACRUM 0:119624335925 178
MACRUM 0:119624335925 179 #ifndef NDEBUG
MACRUM 0:119624335925 180 if (!(_parser.send(SPWFXX_SEND_GET_CONS_STATE)
MACRUM 0:119624335925 181 && _recv_ok())) {
MACRUM 0:119624335925 182 debug_if(_dbg_on, "\r\nSPWF> error getting console state\r\n");
MACRUM 0:119624335925 183 return false;
MACRUM 0:119624335925 184 }
MACRUM 0:119624335925 185
MACRUM 0:119624335925 186 if (!(_parser.send(SPWFXX_SEND_GET_CONS_SPEED)
MACRUM 0:119624335925 187 && _recv_ok())) {
MACRUM 0:119624335925 188 debug_if(_dbg_on, "\r\nSPWF> error getting console speed\r\n");
MACRUM 0:119624335925 189 return false;
MACRUM 0:119624335925 190 }
MACRUM 0:119624335925 191
MACRUM 0:119624335925 192 if (!(_parser.send(SPWFXX_SEND_GET_HWFC_STATE)
MACRUM 0:119624335925 193 && _recv_ok())) {
MACRUM 0:119624335925 194 debug_if(_dbg_on, "\r\nSPWF> error getting hwfc state\r\n");
MACRUM 0:119624335925 195 return false;
MACRUM 0:119624335925 196 }
MACRUM 0:119624335925 197
MACRUM 0:119624335925 198 #if (MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1) || defined(IDW01M1_FW_REL_35X)
MACRUM 0:119624335925 199 /* betzw: IDW01M1 FW versions <3.5 seem to have problems with the following two commands.
MACRUM 0:119624335925 200 * For the sake of simplicity, just excluding them for IDW01M1 in general.
MACRUM 0:119624335925 201 */
MACRUM 0:119624335925 202 if (!(_parser.send(SPWFXX_SEND_GET_CONS_DELIM)
MACRUM 0:119624335925 203 && _recv_ok())) {
MACRUM 0:119624335925 204 debug_if(_dbg_on, "\r\nSPWF> error getting console delimiter\r\n");
MACRUM 0:119624335925 205 return false;
MACRUM 0:119624335925 206 }
MACRUM 0:119624335925 207
MACRUM 0:119624335925 208 if (!(_parser.send(SPWFXX_SEND_GET_CONS_ERRS)
MACRUM 0:119624335925 209 && _recv_ok())) {
MACRUM 0:119624335925 210 debug_if(_dbg_on, "\r\nSPWF> error getting console error setting\r\n");
MACRUM 0:119624335925 211 return false;
MACRUM 0:119624335925 212 }
MACRUM 0:119624335925 213 #endif // (MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1) || defined(IDW01M1_FW_REL_35X)
MACRUM 0:119624335925 214
MACRUM 0:119624335925 215 if (!(_parser.send("AT+S.GCFG=sleep_enabled")
MACRUM 0:119624335925 216 && _recv_ok())) {
MACRUM 0:119624335925 217 debug_if(_dbg_on, "\r\nSPWF> error getting sleep state enabled\r\n");
MACRUM 0:119624335925 218 return false;
MACRUM 0:119624335925 219 }
MACRUM 0:119624335925 220
MACRUM 0:119624335925 221 if (!(_parser.send("AT+S.GCFG=wifi_powersave")
MACRUM 0:119624335925 222 && _recv_ok())) {
MACRUM 0:119624335925 223 debug_if(_dbg_on, "\r\nSPWF> error getting powersave mode\r\n");
MACRUM 0:119624335925 224 return false;
MACRUM 0:119624335925 225 }
MACRUM 0:119624335925 226
MACRUM 0:119624335925 227 if (!(_parser.send("AT+S.GCFG=standby_enabled")
MACRUM 0:119624335925 228 && _recv_ok())) {
MACRUM 0:119624335925 229 debug_if(_dbg_on, "\r\nSPWF> error getting standby state enabled\r\n");
MACRUM 0:119624335925 230 return false;
MACRUM 0:119624335925 231 }
MACRUM 0:119624335925 232 #endif
MACRUM 0:119624335925 233
MACRUM 0:119624335925 234 return true;
MACRUM 0:119624335925 235 }
MACRUM 0:119624335925 236
MACRUM 0:119624335925 237 bool SPWFSAxx::_wait_console_active(void) {
MACRUM 0:119624335925 238 int trials = 0;
MACRUM 0:119624335925 239
MACRUM 0:119624335925 240 while(true) {
MACRUM 0:119624335925 241 if (_parser.recv("+WIND:0:Console active\n") && _recv_delim_lf()) {
MACRUM 0:119624335925 242 debug_if(_dbg_on, "AT^ +WIND:0:Console active\r\n");
MACRUM 0:119624335925 243 return true;
MACRUM 0:119624335925 244 }
MACRUM 0:119624335925 245 if(++trials >= SPWFXX_MAX_TRIALS) {
MACRUM 0:119624335925 246 debug("\r\nSPWF> ERROR: Should never happen! (%s, %d)\r\n", __func__, __LINE__);
MACRUM 0:119624335925 247 empty_rx_buffer();
MACRUM 0:119624335925 248 return false;
MACRUM 0:119624335925 249 }
MACRUM 0:119624335925 250 }
MACRUM 0:119624335925 251 }
MACRUM 0:119624335925 252
MACRUM 0:119624335925 253 bool SPWFSAxx::_wait_wifi_hw_started(void) {
MACRUM 0:119624335925 254 int trials = 0;
MACRUM 0:119624335925 255
MACRUM 0:119624335925 256 while(true) {
MACRUM 0:119624335925 257 if (_parser.recv("+WIND:32:WiFi Hardware Started\n") && _recv_delim_lf()) {
MACRUM 0:119624335925 258 debug_if(_dbg_on, "AT^ +WIND:32:WiFi Hardware Started\r\n");
MACRUM 0:119624335925 259 return true;
MACRUM 0:119624335925 260 }
MACRUM 0:119624335925 261 if(++trials >= SPWFXX_MAX_TRIALS) {
MACRUM 0:119624335925 262 debug("\r\nSPWF> ERROR: Should never happen! (%s, %d)\r\n", __func__, __LINE__);
MACRUM 0:119624335925 263 empty_rx_buffer();
MACRUM 0:119624335925 264 return false;
MACRUM 0:119624335925 265 }
MACRUM 0:119624335925 266 }
MACRUM 0:119624335925 267 }
MACRUM 0:119624335925 268
MACRUM 0:119624335925 269 bool SPWFSAxx::hw_reset(void)
MACRUM 0:119624335925 270 {
MACRUM 0:119624335925 271 #if (MBED_CONF_IDW0XX1_EXPANSION_BOARD != IDW04A1) || !defined(IDW04A1_WIFI_HW_BUG_WA) // betzw: HW reset doesn't work as expected on unmodified X_NUCLEO_IDW04A1 expansion boards
MACRUM 0:119624335925 272 _reset.write(0);
MACRUM 0:119624335925 273 wait_ms(200);
MACRUM 0:119624335925 274 _reset.write(1);
MACRUM 0:119624335925 275 #else // (MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1) && defined(IDW04A1_WIFI_HW_BUG_WA): substitute with SW reset
MACRUM 0:119624335925 276 _parser.send(SPWFXX_SEND_SW_RESET);
MACRUM 0:119624335925 277 #endif // (MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1) && defined(IDW04A1_WIFI_HW_BUG_WA)
MACRUM 0:119624335925 278 return _wait_console_active();
MACRUM 0:119624335925 279 }
MACRUM 0:119624335925 280
MACRUM 0:119624335925 281 bool SPWFSAxx::reset(void)
MACRUM 0:119624335925 282 {
MACRUM 0:119624335925 283 bool ret;
MACRUM 0:119624335925 284
MACRUM 0:119624335925 285 /* save current setting in flash */
MACRUM 0:119624335925 286 if(!(_parser.send(SPWFXX_SEND_SAVE_SETTINGS) && _recv_ok()))
MACRUM 0:119624335925 287 {
MACRUM 0:119624335925 288 debug_if(_dbg_on, "\r\nSPWF> error saving configuration to flash (%s, %d)\r\n", __func__, __LINE__);
MACRUM 0:119624335925 289 return false;
MACRUM 0:119624335925 290 }
MACRUM 0:119624335925 291
MACRUM 0:119624335925 292 if(!_parser.send(SPWFXX_SEND_SW_RESET)) return false; /* betzw - NOTE: "keep the current state and reset the device".
MACRUM 0:119624335925 293 We assume that the module informs us about the
MACRUM 0:119624335925 294 eventual closing of sockets via "WIND" asynchronous
MACRUM 0:119624335925 295 indications! So everything regarding the clean-up
MACRUM 0:119624335925 296 of these situations is handled there. */
MACRUM 0:119624335925 297
MACRUM 0:119624335925 298 /* waiting for HW to start */
MACRUM 0:119624335925 299 ret = _wait_wifi_hw_started();
MACRUM 0:119624335925 300
MACRUM 0:119624335925 301 return ret;
MACRUM 0:119624335925 302 }
MACRUM 0:119624335925 303
MACRUM 0:119624335925 304 /* Security Mode
MACRUM 0:119624335925 305 None = 0,
MACRUM 0:119624335925 306 WEP = 1,
MACRUM 0:119624335925 307 WPA_Personal = 2,
MACRUM 0:119624335925 308 */
MACRUM 0:119624335925 309 bool SPWFSAxx::connect(const char *ap, const char *passPhrase, int securityMode)
MACRUM 0:119624335925 310 {
MACRUM 0:119624335925 311 int trials;
MACRUM 0:119624335925 312
MACRUM 0:119624335925 313 BlockExecuter netsock_wa_obj(Callback<void()>(this, &SPWFSAxx::_unblock_event_callback),
MACRUM 0:119624335925 314 Callback<void()>(this, &SPWFSAxx::_block_event_callback)); /* disable calling (external) callback in IRQ context */
MACRUM 0:119624335925 315
MACRUM 0:119624335925 316 //AT+S.SCFG=wifi_wpa_psk_text,%s
MACRUM 0:119624335925 317 if(!(_parser.send("AT+S.SCFG=wifi_wpa_psk_text,%s", passPhrase) && _recv_ok()))
MACRUM 0:119624335925 318 {
MACRUM 0:119624335925 319 debug_if(_dbg_on, "\r\nSPWF> error pass set\r\n");
MACRUM 0:119624335925 320 return false;
MACRUM 0:119624335925 321 }
MACRUM 0:119624335925 322
MACRUM 0:119624335925 323 //AT+S.SSIDTXT=%s
MACRUM 0:119624335925 324 if(!(_parser.send("AT+S.SSIDTXT=%s", ap) && _recv_ok()))
MACRUM 0:119624335925 325 {
MACRUM 0:119624335925 326 debug_if(_dbg_on, "\r\nSPWF> error ssid set\r\n");
MACRUM 0:119624335925 327 return false;
MACRUM 0:119624335925 328 }
MACRUM 0:119624335925 329
MACRUM 0:119624335925 330 //AT+S.SCFG=wifi_priv_mode,%d
MACRUM 0:119624335925 331 if(!(_parser.send("AT+S.SCFG=wifi_priv_mode,%d", securityMode) && _recv_ok()))
MACRUM 0:119624335925 332 {
MACRUM 0:119624335925 333 debug_if(_dbg_on, "\r\nSPWF> error security mode set\r\n");
MACRUM 0:119624335925 334 return false;
MACRUM 0:119624335925 335 }
MACRUM 0:119624335925 336
MACRUM 0:119624335925 337 /*set STA mode (0->idle, 1->STA,3->miniAP, 2->IBSS)*/
MACRUM 0:119624335925 338 if(!(_parser.send("AT+S.SCFG=wifi_mode,1") && _recv_ok()))
MACRUM 0:119624335925 339 {
MACRUM 0:119624335925 340 debug_if(_dbg_on, "\r\nSPWF> error WiFi mode set 1 (STA)\r\n");
MACRUM 0:119624335925 341 return false;
MACRUM 0:119624335925 342 }
MACRUM 0:119624335925 343
MACRUM 0:119624335925 344 /* sw reset */
MACRUM 0:119624335925 345 if(!reset()) {
MACRUM 0:119624335925 346 debug_if(_dbg_on, "\r\nSPWF> SW reset failed (%s, %d)\r\n", __func__, __LINE__);
MACRUM 0:119624335925 347 return false;
MACRUM 0:119624335925 348 }
MACRUM 0:119624335925 349
MACRUM 0:119624335925 350 trials = 0;
MACRUM 0:119624335925 351 while(true) {
MACRUM 0:119624335925 352 if(_parser.recv("%255[^\n]\n", _msg_buffer) && _recv_delim_lf())
MACRUM 0:119624335925 353 {
MACRUM 0:119624335925 354 if(strstr(_msg_buffer, ":24:") != NULL) { // WiFi Up
MACRUM 0:119624335925 355 debug_if(_dbg_on, "AT^ %s\n", _msg_buffer);
MACRUM 0:119624335925 356 if(strchr(_msg_buffer, '.') != NULL) { // IPv4 address
MACRUM 0:119624335925 357 break;
MACRUM 0:119624335925 358 } else {
MACRUM 0:119624335925 359 continue;
MACRUM 0:119624335925 360 }
MACRUM 0:119624335925 361 }
MACRUM 0:119624335925 362 if(strstr(_msg_buffer, ":40:") != NULL) { // Deauthentication
MACRUM 0:119624335925 363 debug_if(_dbg_on, "AT~ %s\n", _msg_buffer);
MACRUM 0:119624335925 364 if(++trials < SPWFXX_MAX_TRIALS) { // give it three trials
MACRUM 0:119624335925 365 continue;
MACRUM 0:119624335925 366 }
MACRUM 0:119624335925 367 disconnect();
MACRUM 0:119624335925 368 empty_rx_buffer();
MACRUM 0:119624335925 369 return false;
MACRUM 0:119624335925 370 } else {
MACRUM 0:119624335925 371 debug_if(_dbg_on, "AT] %s\n", _msg_buffer);
MACRUM 0:119624335925 372 }
MACRUM 0:119624335925 373 continue;
MACRUM 0:119624335925 374 }
MACRUM 0:119624335925 375 if(++trials >= SPWFXX_MAX_TRIALS) {
MACRUM 0:119624335925 376 debug("\r\nSPWF> ERROR: Should never happen! (%s, %d)\r\n", __func__, __LINE__);
MACRUM 0:119624335925 377 empty_rx_buffer();
MACRUM 0:119624335925 378 return false;
MACRUM 0:119624335925 379 }
MACRUM 0:119624335925 380 }
MACRUM 0:119624335925 381
MACRUM 0:119624335925 382 return true;
MACRUM 0:119624335925 383 }
MACRUM 0:119624335925 384
MACRUM 0:119624335925 385 bool SPWFSAxx::disconnect(void)
MACRUM 0:119624335925 386 {
MACRUM 0:119624335925 387 BlockExecuter netsock_wa_obj(Callback<void()>(this, &SPWFSAxx::_unblock_event_callback),
MACRUM 0:119624335925 388 Callback<void()>(this, &SPWFSAxx::_block_event_callback)); /* disable calling (external) callback in IRQ context */
MACRUM 0:119624335925 389
MACRUM 0:119624335925 390 #if MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1
MACRUM 0:119624335925 391 /*disable Wi-Fi device*/
MACRUM 0:119624335925 392 if(!(_parser.send("AT+S.WIFI=0") && _recv_ok()))
MACRUM 0:119624335925 393 {
MACRUM 0:119624335925 394 debug_if(_dbg_on, "\r\nSPWF> error disabling WiFi\r\n");
MACRUM 0:119624335925 395 return false;
MACRUM 0:119624335925 396 }
MACRUM 0:119624335925 397 #endif // IDW04A1
MACRUM 0:119624335925 398
MACRUM 0:119624335925 399 /*set idle mode (0->idle, 1->STA,3->miniAP, 2->IBSS)*/
MACRUM 0:119624335925 400 if(!(_parser.send("AT+S.SCFG=wifi_mode,0") && _recv_ok()))
MACRUM 0:119624335925 401 {
MACRUM 0:119624335925 402 debug_if(_dbg_on, "\r\nSPWF> error WiFi mode set idle (%d)\r\n", __LINE__);
MACRUM 0:119624335925 403 return false;
MACRUM 0:119624335925 404 }
MACRUM 0:119624335925 405
MACRUM 0:119624335925 406 #if MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1
MACRUM 0:119624335925 407 /*enable Wi-Fi device*/
MACRUM 0:119624335925 408 if(!(_parser.send("AT+S.WIFI=1") && _recv_ok()))
MACRUM 0:119624335925 409 {
MACRUM 0:119624335925 410 debug_if(_dbg_on, "\r\nSPWF> error enabling WiFi\r\n");
MACRUM 0:119624335925 411 return false;
MACRUM 0:119624335925 412 }
MACRUM 0:119624335925 413 #endif // IDW04A1
MACRUM 0:119624335925 414
MACRUM 0:119624335925 415 // reset module
MACRUM 0:119624335925 416 if(!reset()) {
MACRUM 0:119624335925 417 debug_if(_dbg_on, "\r\nSPWF> SW reset failed (%s, %d)\r\n", __func__, __LINE__);
MACRUM 0:119624335925 418 return false;
MACRUM 0:119624335925 419 }
MACRUM 0:119624335925 420
MACRUM 0:119624335925 421 /* clean up state */
MACRUM 0:119624335925 422 _associated_interface.inner_constructor();
MACRUM 0:119624335925 423 _free_all_packets();
MACRUM 0:119624335925 424
MACRUM 0:119624335925 425 return true;
MACRUM 0:119624335925 426 }
MACRUM 0:119624335925 427
MACRUM 0:119624335925 428 const char *SPWFSAxx::getIPAddress(void)
MACRUM 0:119624335925 429 {
MACRUM 0:119624335925 430 unsigned int n1, n2, n3, n4;
MACRUM 0:119624335925 431
MACRUM 0:119624335925 432 BlockExecuter netsock_wa_obj(Callback<void()>(this, &SPWFSAxx::_unblock_event_callback),
MACRUM 0:119624335925 433 Callback<void()>(this, &SPWFSAxx::_block_event_callback)); /* disable calling (external) callback in IRQ context */
MACRUM 0:119624335925 434
MACRUM 0:119624335925 435 if (!(_parser.send("AT+S.STS=ip_ipaddr")
MACRUM 0:119624335925 436 && _parser.recv(SPWFXX_RECV_IP_ADDR, &n1, &n2, &n3, &n4)
MACRUM 0:119624335925 437 && _recv_ok())) {
MACRUM 0:119624335925 438 debug_if(_dbg_on, "\r\nSPWF> get IP address error\r\n");
MACRUM 0:119624335925 439 return NULL;
MACRUM 0:119624335925 440 }
MACRUM 0:119624335925 441
MACRUM 0:119624335925 442 debug_if(_dbg_on, "AT^ ip_ipaddr = %u.%u.%u.%u\r\n", n1, n2, n3, n4);
MACRUM 0:119624335925 443
MACRUM 0:119624335925 444 sprintf((char*)_ip_buffer,"%u.%u.%u.%u", n1, n2, n3, n4);
MACRUM 0:119624335925 445 return _ip_buffer;
MACRUM 0:119624335925 446 }
MACRUM 0:119624335925 447
MACRUM 0:119624335925 448 const char *SPWFSAxx::getGateway(void)
MACRUM 0:119624335925 449 {
MACRUM 0:119624335925 450 unsigned int n1, n2, n3, n4;
MACRUM 0:119624335925 451
MACRUM 0:119624335925 452 BlockExecuter netsock_wa_obj(Callback<void()>(this, &SPWFSAxx::_unblock_event_callback),
MACRUM 0:119624335925 453 Callback<void()>(this, &SPWFSAxx::_block_event_callback)); /* disable calling (external) callback in IRQ context */
MACRUM 0:119624335925 454
MACRUM 0:119624335925 455 if (!(_parser.send("AT+S.STS=ip_gw")
MACRUM 0:119624335925 456 && _parser.recv(SPWFXX_RECV_GATEWAY, &n1, &n2, &n3, &n4)
MACRUM 0:119624335925 457 && _recv_ok())) {
MACRUM 0:119624335925 458 debug_if(_dbg_on, "\r\nSPWF> get gateway error\r\n");
MACRUM 0:119624335925 459 return NULL;
MACRUM 0:119624335925 460 }
MACRUM 0:119624335925 461
MACRUM 0:119624335925 462 debug_if(_dbg_on, "AT^ ip_gw = %u.%u.%u.%u\r\n", n1, n2, n3, n4);
MACRUM 0:119624335925 463
MACRUM 0:119624335925 464 sprintf((char*)_gateway_buffer,"%u.%u.%u.%u", n1, n2, n3, n4);
MACRUM 0:119624335925 465 return _gateway_buffer;
MACRUM 0:119624335925 466 }
MACRUM 0:119624335925 467
MACRUM 0:119624335925 468 const char *SPWFSAxx::getNetmask(void)
MACRUM 0:119624335925 469 {
MACRUM 0:119624335925 470 unsigned int n1, n2, n3, n4;
MACRUM 0:119624335925 471
MACRUM 0:119624335925 472 BlockExecuter netsock_wa_obj(Callback<void()>(this, &SPWFSAxx::_unblock_event_callback),
MACRUM 0:119624335925 473 Callback<void()>(this, &SPWFSAxx::_block_event_callback)); /* disable calling (external) callback in IRQ context */
MACRUM 0:119624335925 474
MACRUM 0:119624335925 475 if (!(_parser.send("AT+S.STS=ip_netmask")
MACRUM 0:119624335925 476 && _parser.recv(SPWFXX_RECV_NETMASK, &n1, &n2, &n3, &n4)
MACRUM 0:119624335925 477 && _recv_ok())) {
MACRUM 0:119624335925 478 debug_if(_dbg_on, "\r\nSPWF> get netmask error\r\n");
MACRUM 0:119624335925 479 return NULL;
MACRUM 0:119624335925 480 }
MACRUM 0:119624335925 481
MACRUM 0:119624335925 482 debug_if(_dbg_on, "AT^ ip_netmask = %u.%u.%u.%u\r\n", n1, n2, n3, n4);
MACRUM 0:119624335925 483
MACRUM 0:119624335925 484 sprintf((char*)_netmask_buffer,"%u.%u.%u.%u", n1, n2, n3, n4);
MACRUM 0:119624335925 485 return _netmask_buffer;
MACRUM 0:119624335925 486 }
MACRUM 0:119624335925 487
MACRUM 0:119624335925 488 int8_t SPWFSAxx::getRssi(void)
MACRUM 0:119624335925 489 {
MACRUM 0:119624335925 490 int ret;
MACRUM 0:119624335925 491
MACRUM 0:119624335925 492 BlockExecuter netsock_wa_obj(Callback<void()>(this, &SPWFSAxx::_unblock_event_callback),
MACRUM 0:119624335925 493 Callback<void()>(this, &SPWFSAxx::_block_event_callback)); /* disable calling (external) callback in IRQ context */
MACRUM 0:119624335925 494
MACRUM 0:119624335925 495 if (!(_parser.send("AT+S.PEERS=0,rx_rssi")
MACRUM 0:119624335925 496 && _parser.recv(SPWFXX_RECV_RX_RSSI, &ret)
MACRUM 0:119624335925 497 && _recv_ok())) {
MACRUM 0:119624335925 498 debug_if(_dbg_on, "\r\nSPWF> get RX rssi error\r\n");
MACRUM 0:119624335925 499 return 0;
MACRUM 0:119624335925 500 }
MACRUM 0:119624335925 501
MACRUM 0:119624335925 502 return (int8_t)ret;
MACRUM 0:119624335925 503 }
MACRUM 0:119624335925 504
MACRUM 0:119624335925 505 const char *SPWFSAxx::getMACAddress(void)
MACRUM 0:119624335925 506 {
MACRUM 0:119624335925 507 unsigned int n1, n2, n3, n4, n5, n6;
MACRUM 0:119624335925 508
MACRUM 0:119624335925 509 BlockExecuter netsock_wa_obj(Callback<void()>(this, &SPWFSAxx::_unblock_event_callback),
MACRUM 0:119624335925 510 Callback<void()>(this, &SPWFSAxx::_block_event_callback)); /* disable calling (external) callback in IRQ context */
MACRUM 0:119624335925 511
MACRUM 0:119624335925 512 if (!(_parser.send("AT+S.GCFG=nv_wifi_macaddr")
MACRUM 0:119624335925 513 && _parser.recv(SPWFXX_RECV_MAC_ADDR, &n1, &n2, &n3, &n4, &n5, &n6)
MACRUM 0:119624335925 514 && _recv_ok())) {
MACRUM 0:119624335925 515 debug_if(_dbg_on, "\r\nSPWF> get MAC address error\r\n");
MACRUM 0:119624335925 516 return 0;
MACRUM 0:119624335925 517 }
MACRUM 0:119624335925 518
MACRUM 0:119624335925 519 debug_if(_dbg_on, "AT^ nv_wifi_macaddr = %x:%x:%x:%x:%x:%x\r\n", n1, n2, n3, n4, n5, n6);
MACRUM 0:119624335925 520
MACRUM 0:119624335925 521 sprintf((char*)_mac_buffer,"%02X:%02X:%02X:%02X:%02X:%02X", n1, n2, n3, n4, n5, n6);
MACRUM 0:119624335925 522 return _mac_buffer;
MACRUM 0:119624335925 523 }
MACRUM 0:119624335925 524
MACRUM 0:119624335925 525 bool SPWFSAxx::isConnected(void)
MACRUM 0:119624335925 526 {
MACRUM 0:119624335925 527 return _associated_interface._connected_to_network;
MACRUM 0:119624335925 528 }
MACRUM 0:119624335925 529
MACRUM 0:119624335925 530 nsapi_size_or_error_t SPWFSAxx::send(int spwf_id, const void *data, uint32_t amount, int internal_id)
MACRUM 0:119624335925 531 {
MACRUM 0:119624335925 532 uint32_t sent = 0U, to_send;
MACRUM 0:119624335925 533 nsapi_size_or_error_t ret;
MACRUM 0:119624335925 534
MACRUM 0:119624335925 535 BlockExecuter netsock_wa_obj(Callback<void()>(this, &SPWFSAxx::_unblock_event_callback),
MACRUM 0:119624335925 536 Callback<void()>(this, &SPWFSAxx::_block_event_callback)); /* disable calling (external) callback in IRQ context */
MACRUM 0:119624335925 537
MACRUM 0:119624335925 538 _process_winds(); // perform async indication handling (to early detect eventually closed sockets)
MACRUM 0:119624335925 539
MACRUM 0:119624335925 540 /* betzw - WORK AROUND module FW issues: split up big packages in smaller ones */
MACRUM 0:119624335925 541 for(to_send = (amount > SPWFXX_SEND_RECV_PKTSIZE) ? SPWFXX_SEND_RECV_PKTSIZE : amount;
MACRUM 0:119624335925 542 sent < amount;
MACRUM 0:119624335925 543 to_send = ((amount - sent) > SPWFXX_SEND_RECV_PKTSIZE) ? SPWFXX_SEND_RECV_PKTSIZE : (amount - sent)) {
MACRUM 0:119624335925 544 {
MACRUM 0:119624335925 545 BlockExecuter bh_handler(Callback<void()>(this, &SPWFSAxx::_execute_bottom_halves));
MACRUM 0:119624335925 546
MACRUM 0:119624335925 547 // betzw - TODO: handle different errors more accurately!
MACRUM 0:119624335925 548 if (!_associated_interface._socket_is_still_connected(internal_id)) {
MACRUM 0:119624335925 549 debug_if(_dbg_on, "\r\nSPWF> Socket not connected anymore: sent=%u, to_send=%u! (%s, %d)\r\n", sent, to_send, __func__, __LINE__);
MACRUM 0:119624335925 550 break;
MACRUM 0:119624335925 551 } else if(!_parser.send("AT+S.SOCKW=%d,%d", spwf_id, (unsigned int)to_send)) {
MACRUM 0:119624335925 552 debug_if(_dbg_on, "\r\nSPWF> Sending command failed: sent=%u, to_send=%u! (%s, %d)\r\n", sent, to_send, __func__, __LINE__);
MACRUM 0:119624335925 553 break;
MACRUM 0:119624335925 554 } else if(_parser.write(((char*)data)+sent, (int)to_send) != (int)to_send) {
MACRUM 0:119624335925 555 debug_if(_dbg_on, "\r\nSPWF> Sending data failed: sent=%u, to_send=%u! (%s, %d)\r\n", sent, to_send, __func__, __LINE__);
MACRUM 0:119624335925 556 break;
MACRUM 0:119624335925 557 } else if(!_recv_ok()) {
MACRUM 0:119624335925 558 debug_if(_dbg_on, "\r\nSPWF> Sending did not receive OK: sent=%u, to_send=%u! (%s, %d)\r\n", sent, to_send, __func__, __LINE__);
MACRUM 0:119624335925 559 break;
MACRUM 0:119624335925 560 }
MACRUM 0:119624335925 561 }
MACRUM 0:119624335925 562
MACRUM 0:119624335925 563 sent += to_send;
MACRUM 0:119624335925 564 }
MACRUM 0:119624335925 565
MACRUM 0:119624335925 566 if(sent > 0) { // `sent == 0` indicates a potential error
MACRUM 0:119624335925 567 ret = sent;
MACRUM 0:119624335925 568 } else if(amount == 0) {
MACRUM 0:119624335925 569 ret = NSAPI_ERROR_OK;
MACRUM 0:119624335925 570 } else if(_associated_interface._socket_is_still_connected(internal_id)) {
MACRUM 0:119624335925 571 ret = NSAPI_ERROR_DEVICE_ERROR;
MACRUM 0:119624335925 572 } else {
MACRUM 0:119624335925 573 ret = NSAPI_ERROR_CONNECTION_LOST;
MACRUM 0:119624335925 574 }
MACRUM 0:119624335925 575
MACRUM 0:119624335925 576 return ret;
MACRUM 0:119624335925 577 }
MACRUM 0:119624335925 578
MACRUM 0:119624335925 579 int SPWFSAxx::_read_len(int spwf_id) {
MACRUM 0:119624335925 580 unsigned int amount;
MACRUM 0:119624335925 581
MACRUM 0:119624335925 582 if (!(_parser.send("AT+S.SOCKQ=%d", spwf_id)
MACRUM 0:119624335925 583 && _parser.recv(SPWFXX_RECV_DATALEN, &amount)
MACRUM 0:119624335925 584 && _recv_ok())) {
MACRUM 0:119624335925 585 debug_if(_dbg_on, "\r\nSPWF> %s failed\r\n", __func__);
MACRUM 0:119624335925 586 return SPWFXX_ERR_LEN;
MACRUM 0:119624335925 587 }
MACRUM 0:119624335925 588
MACRUM 0:119624335925 589 if(amount > 0) {
MACRUM 0:119624335925 590 debug_if(_dbg_on, "\r\nSPWF> %s():\t\t%d:%d\r\n", __func__, spwf_id, amount);
MACRUM 0:119624335925 591 }
MACRUM 0:119624335925 592
MACRUM 0:119624335925 593 MBED_ASSERT(((int)amount) >= 0);
MACRUM 0:119624335925 594
MACRUM 0:119624335925 595 return (int)amount;
MACRUM 0:119624335925 596 }
MACRUM 0:119624335925 597
MACRUM 0:119624335925 598 #define SPWFXX_WINDS_OFF "0xFFFFFFFF"
MACRUM 0:119624335925 599
MACRUM 0:119624335925 600 void SPWFSAxx::_winds_on(void) {
MACRUM 0:119624335925 601 MBED_ASSERT(_is_event_callback_blocked());
MACRUM 0:119624335925 602
MACRUM 0:119624335925 603 if(!(_parser.send(SPWFXX_SEND_WIND_OFF_HIGH SPWFXX_WINDS_HIGH_ON) && _recv_ok())) {
MACRUM 0:119624335925 604 debug_if(_dbg_on, "\r\nSPWF> %s failed at line #%d\r\n", __func__, __LINE__);
MACRUM 0:119624335925 605 }
MACRUM 0:119624335925 606 if(!(_parser.send(SPWFXX_SEND_WIND_OFF_MEDIUM SPWFXX_WINDS_MEDIUM_ON) && _recv_ok())) {
MACRUM 0:119624335925 607 debug_if(_dbg_on, "\r\nSPWF> %s failed at line #%d\r\n", __func__, __LINE__);
MACRUM 0:119624335925 608 }
MACRUM 0:119624335925 609 if(!(_parser.send(SPWFXX_SEND_WIND_OFF_LOW SPWFXX_WINDS_LOW_ON) && _recv_ok())) {
MACRUM 0:119624335925 610 debug_if(_dbg_on, "\r\nSPWF> %s failed at line #%d\r\n", __func__, __LINE__);
MACRUM 0:119624335925 611 }
MACRUM 0:119624335925 612 }
MACRUM 0:119624335925 613
MACRUM 0:119624335925 614 /* Define beyond macro in case you want to report back failures in switching off WINDs to the caller */
MACRUM 0:119624335925 615 // #define SPWFXX_SOWF
MACRUM 0:119624335925 616 /* Note: in case of error blocking has been (tried to be) lifted */
MACRUM 0:119624335925 617 bool SPWFSAxx::_winds_off(void) {
MACRUM 0:119624335925 618 MBED_ASSERT(_is_event_callback_blocked());
MACRUM 0:119624335925 619
MACRUM 0:119624335925 620 if (!(_parser.send(SPWFXX_SEND_WIND_OFF_LOW SPWFXX_WINDS_OFF)
MACRUM 0:119624335925 621 && _recv_ok())) {
MACRUM 0:119624335925 622 debug_if(_dbg_on, "\r\nSPWF> %s failed at line #%d\r\n", __func__, __LINE__);
MACRUM 0:119624335925 623 #ifdef SPWFXX_SOWF // betzw: try to continue
MACRUM 0:119624335925 624 _winds_on();
MACRUM 0:119624335925 625 return false;
MACRUM 0:119624335925 626 #endif
MACRUM 0:119624335925 627 }
MACRUM 0:119624335925 628
MACRUM 0:119624335925 629 if (!(_parser.send(SPWFXX_SEND_WIND_OFF_MEDIUM SPWFXX_WINDS_OFF)
MACRUM 0:119624335925 630 && _recv_ok())) {
MACRUM 0:119624335925 631 debug_if(_dbg_on, "\r\nSPWF> %s failed at line #%d\r\n", __func__, __LINE__);
MACRUM 0:119624335925 632 #ifdef SPWFXX_SOWF // betzw: try to continue
MACRUM 0:119624335925 633 _winds_on();
MACRUM 0:119624335925 634 return false;
MACRUM 0:119624335925 635 #endif
MACRUM 0:119624335925 636 }
MACRUM 0:119624335925 637
MACRUM 0:119624335925 638 if (!(_parser.send(SPWFXX_SEND_WIND_OFF_HIGH SPWFXX_WINDS_OFF)
MACRUM 0:119624335925 639 && _recv_ok())) {
MACRUM 0:119624335925 640 debug_if(_dbg_on, "\r\nSPWF> %s failed at line #%d\r\n", __func__, __LINE__);
MACRUM 0:119624335925 641 #ifdef SPWFXX_SOWF // betzw: try to continue
MACRUM 0:119624335925 642 _winds_on();
MACRUM 0:119624335925 643 return false;
MACRUM 0:119624335925 644 #endif
MACRUM 0:119624335925 645 }
MACRUM 0:119624335925 646
MACRUM 0:119624335925 647 return true;
MACRUM 0:119624335925 648 }
MACRUM 0:119624335925 649
MACRUM 0:119624335925 650 void SPWFSAxx::_execute_bottom_halves(void) {
MACRUM 0:119624335925 651 _network_lost_handler_bh();
MACRUM 0:119624335925 652 _packet_handler_bh();
MACRUM 0:119624335925 653 }
MACRUM 0:119624335925 654
MACRUM 0:119624335925 655 void SPWFSAxx::_read_in_pending(void) {
MACRUM 0:119624335925 656 static int internal_id_cnt = 0;
MACRUM 0:119624335925 657
MACRUM 0:119624335925 658 while(_is_data_pending()) {
MACRUM 0:119624335925 659 if(_associated_interface._socket_has_connected(internal_id_cnt)) {
MACRUM 0:119624335925 660 int spwf_id = _associated_interface._ids[internal_id_cnt].spwf_id;
MACRUM 0:119624335925 661
MACRUM 0:119624335925 662 if(_is_data_pending(spwf_id)) {
MACRUM 0:119624335925 663 int amount;
MACRUM 0:119624335925 664
MACRUM 0:119624335925 665 amount = _read_in_pkt(spwf_id, false);
MACRUM 0:119624335925 666 if(amount == SPWFXX_ERR_OOM) { /* consider only 'SPWFXX_ERR_OOM' as non recoverable */
MACRUM 0:119624335925 667 return;
MACRUM 0:119624335925 668 }
MACRUM 0:119624335925 669 }
MACRUM 0:119624335925 670
MACRUM 0:119624335925 671 if(!_is_data_pending(spwf_id)) {
MACRUM 0:119624335925 672 internal_id_cnt++;
MACRUM 0:119624335925 673 internal_id_cnt %= SPWFSA_SOCKET_COUNT;
MACRUM 0:119624335925 674 }
MACRUM 0:119624335925 675 } else {
MACRUM 0:119624335925 676 internal_id_cnt++;
MACRUM 0:119624335925 677 internal_id_cnt %= SPWFSA_SOCKET_COUNT;
MACRUM 0:119624335925 678 }
MACRUM 0:119624335925 679 }
MACRUM 0:119624335925 680 }
MACRUM 0:119624335925 681
MACRUM 0:119624335925 682 /* Note: returns
MACRUM 0:119624335925 683 * 'SPWFXX_ERR_OK' in case of success
MACRUM 0:119624335925 684 * 'SPWFXX_ERR_OOM' in case of "out of memory"
MACRUM 0:119624335925 685 * 'SPWFXX_ERR_READ' in case of `_read_in()` error
MACRUM 0:119624335925 686 */
MACRUM 0:119624335925 687 int SPWFSAxx::_read_in_packet(int spwf_id, uint32_t amount) {
MACRUM 0:119624335925 688 struct packet *packet = (struct packet*)malloc(sizeof(struct packet) + amount);
MACRUM 0:119624335925 689 if (!packet) {
MACRUM 0:119624335925 690 #ifndef NDEBUG
MACRUM 0:119624335925 691 error("\r\nSPWF> %s(%d): Out of memory!\r\n", __func__, __LINE__);
MACRUM 0:119624335925 692 #else // NDEBUG
MACRUM 0:119624335925 693 debug("\r\nSPWF> %s(%d): Out of memory!\r\n", __func__, __LINE__);
MACRUM 0:119624335925 694 #endif
MACRUM 0:119624335925 695 debug_if(_dbg_on, "\r\nSPWF> %s failed (%d)\r\n", __func__, __LINE__);
MACRUM 0:119624335925 696 return SPWFXX_ERR_OOM; /* out of memory: give up here! */
MACRUM 0:119624335925 697 }
MACRUM 0:119624335925 698
MACRUM 0:119624335925 699 /* init packet */
MACRUM 0:119624335925 700 packet->id = spwf_id;
MACRUM 0:119624335925 701 packet->len = amount;
MACRUM 0:119624335925 702 packet->next = 0;
MACRUM 0:119624335925 703
MACRUM 0:119624335925 704 /* read data in */
MACRUM 0:119624335925 705 if(!(_read_in((char*)(packet + 1), spwf_id, amount) > 0)) {
MACRUM 0:119624335925 706 free(packet);
MACRUM 0:119624335925 707 debug_if(_dbg_on, "\r\nSPWF> %s failed (%d)\r\n", __func__, __LINE__);
MACRUM 0:119624335925 708 return SPWFXX_ERR_READ;
MACRUM 0:119624335925 709 } else {
MACRUM 0:119624335925 710 debug_if(_dbg_on, "\r\nSPWF> %s():\t%d:%d\r\n", __func__, spwf_id, amount);
MACRUM 0:119624335925 711
MACRUM 0:119624335925 712 /* append to packet list */
MACRUM 0:119624335925 713 *_packets_end = packet;
MACRUM 0:119624335925 714 _packets_end = &packet->next;
MACRUM 0:119624335925 715
MACRUM 0:119624335925 716 /* force call of (external) callback */
MACRUM 0:119624335925 717 _call_callback();
MACRUM 0:119624335925 718 }
MACRUM 0:119624335925 719
MACRUM 0:119624335925 720 return SPWFXX_ERR_OK;
MACRUM 0:119624335925 721 }
MACRUM 0:119624335925 722
MACRUM 0:119624335925 723 void SPWFSAxx::_free_packets(int spwf_id) {
MACRUM 0:119624335925 724 // check if any packets are ready for `spwf_id`
MACRUM 0:119624335925 725 for(struct packet **p = &_packets; *p;) {
MACRUM 0:119624335925 726 if ((*p)->id == spwf_id) {
MACRUM 0:119624335925 727 struct packet *q = *p;
MACRUM 0:119624335925 728 if (_packets_end == &(*p)->next) {
MACRUM 0:119624335925 729 _packets_end = p;
MACRUM 0:119624335925 730 }
MACRUM 0:119624335925 731 *p = (*p)->next;
MACRUM 0:119624335925 732 free(q);
MACRUM 0:119624335925 733 } else {
MACRUM 0:119624335925 734 p = &(*p)->next;
MACRUM 0:119624335925 735 }
MACRUM 0:119624335925 736 }
MACRUM 0:119624335925 737 }
MACRUM 0:119624335925 738
MACRUM 0:119624335925 739 void SPWFSAxx::_free_all_packets() {
MACRUM 0:119624335925 740 for (int spwf_id = 0; spwf_id < SPWFSA_SOCKET_COUNT; spwf_id++) {
MACRUM 0:119624335925 741 _free_packets(spwf_id);
MACRUM 0:119624335925 742 }
MACRUM 0:119624335925 743 }
MACRUM 0:119624335925 744
MACRUM 0:119624335925 745 bool SPWFSAxx::close(int spwf_id)
MACRUM 0:119624335925 746 {
MACRUM 0:119624335925 747 bool ret = false;
MACRUM 0:119624335925 748
MACRUM 0:119624335925 749 BlockExecuter netsock_wa_obj(Callback<void()>(this, &SPWFSAxx::_unblock_event_callback),
MACRUM 0:119624335925 750 Callback<void()>(this, &SPWFSAxx::_block_event_callback)); /* disable calling (external) callback in IRQ context */
MACRUM 0:119624335925 751
MACRUM 0:119624335925 752 MBED_ASSERT(((unsigned int)spwf_id) < ((unsigned int)SPWFSA_SOCKET_COUNT)); // `spwf_id` is valid
MACRUM 0:119624335925 753
MACRUM 0:119624335925 754 for(int retry_cnt = 0; retry_cnt < SPWFXX_MAX_TRIALS; retry_cnt++) {
MACRUM 0:119624335925 755 Timer timer;
MACRUM 0:119624335925 756 timer.start();
MACRUM 0:119624335925 757
MACRUM 0:119624335925 758 // Flush out pending data
MACRUM 0:119624335925 759 while(true) {
MACRUM 0:119624335925 760 int amount = _read_in_pkt(spwf_id, true);
MACRUM 0:119624335925 761 if(amount < 0) { // SPWFXX error
MACRUM 0:119624335925 762 /* empty RX buffer & try to close */
MACRUM 0:119624335925 763 empty_rx_buffer();
MACRUM 0:119624335925 764 break;
MACRUM 0:119624335925 765 }
MACRUM 0:119624335925 766 if(amount == 0) break; // no more data to be read
MACRUM 0:119624335925 767
MACRUM 0:119624335925 768 /* Try to work around module API bug:
MACRUM 0:119624335925 769 * break out & try to close after 20 seconds
MACRUM 0:119624335925 770 */
MACRUM 0:119624335925 771 if(timer.read() > 20) {
MACRUM 0:119624335925 772 break;
MACRUM 0:119624335925 773 }
MACRUM 0:119624335925 774
MACRUM 0:119624335925 775 /* immediately free packet(s) (to avoid "out of memory") */
MACRUM 0:119624335925 776 _free_packets(spwf_id);
MACRUM 0:119624335925 777
MACRUM 0:119624335925 778 /* interleave bottom halves */
MACRUM 0:119624335925 779 _execute_bottom_halves();
MACRUM 0:119624335925 780 }
MACRUM 0:119624335925 781
MACRUM 0:119624335925 782 // Close socket
MACRUM 0:119624335925 783 if (_parser.send("AT+S.SOCKC=%d", spwf_id)
MACRUM 0:119624335925 784 && _recv_ok()) {
MACRUM 0:119624335925 785 ret = true;
MACRUM 0:119624335925 786 break; // finish closing
MACRUM 0:119624335925 787 } else { // close failed
MACRUM 0:119624335925 788 debug_if(_dbg_on, "\r\nSPWF> %s failed (%d)\r\n", __func__, __LINE__);
MACRUM 0:119624335925 789 /* interleave bottom halves */
MACRUM 0:119624335925 790 _execute_bottom_halves();
MACRUM 0:119624335925 791
MACRUM 0:119624335925 792 /* free packets */
MACRUM 0:119624335925 793 _free_packets(spwf_id);
MACRUM 0:119624335925 794 }
MACRUM 0:119624335925 795 }
MACRUM 0:119624335925 796
MACRUM 0:119624335925 797 /* anticipate bottom halves */
MACRUM 0:119624335925 798 _execute_bottom_halves();
MACRUM 0:119624335925 799
MACRUM 0:119624335925 800 if(ret) {
MACRUM 0:119624335925 801 /* clear pending data flag (should be redundant) */
MACRUM 0:119624335925 802 _clear_pending_data(spwf_id);
MACRUM 0:119624335925 803
MACRUM 0:119624335925 804 /* free packets for this socket */
MACRUM 0:119624335925 805 _free_packets(spwf_id);
MACRUM 0:119624335925 806
MACRUM 0:119624335925 807 /* reset pending data sizes */
MACRUM 0:119624335925 808 _reset_pending_pkt_sizes(spwf_id);
MACRUM 0:119624335925 809 } else {
MACRUM 0:119624335925 810 debug_if(_dbg_on, "\r\nSPWF> SPWFSAxx::close failed (%d)\r\n", __LINE__);
MACRUM 0:119624335925 811
MACRUM 0:119624335925 812 int internal_id = _associated_interface.get_internal_id(spwf_id);
MACRUM 0:119624335925 813 if(!_associated_interface._socket_is_still_connected(internal_id)) {
MACRUM 0:119624335925 814 /* clear pending data flag (should be redundant) */
MACRUM 0:119624335925 815 _clear_pending_data(spwf_id);
MACRUM 0:119624335925 816
MACRUM 0:119624335925 817 /* free packets for this socket */
MACRUM 0:119624335925 818 _free_packets(spwf_id);
MACRUM 0:119624335925 819
MACRUM 0:119624335925 820 /* reset pending data sizes */
MACRUM 0:119624335925 821 _reset_pending_pkt_sizes(spwf_id);
MACRUM 0:119624335925 822
MACRUM 0:119624335925 823 ret = true;
MACRUM 0:119624335925 824 }
MACRUM 0:119624335925 825 }
MACRUM 0:119624335925 826
MACRUM 0:119624335925 827 return ret;
MACRUM 0:119624335925 828 }
MACRUM 0:119624335925 829
MACRUM 0:119624335925 830 /*
MACRUM 0:119624335925 831 * Buffered serial event handler
MACRUM 0:119624335925 832 *
MACRUM 0:119624335925 833 * Note: executed in IRQ context!
MACRUM 0:119624335925 834 * Note: do not call (external) callback in IRQ context while performing critical module operations
MACRUM 0:119624335925 835 */
MACRUM 0:119624335925 836 void SPWFSAxx::_event_handler(void)
MACRUM 0:119624335925 837 {
MACRUM 0:119624335925 838 if(!_is_event_callback_blocked()) {
MACRUM 0:119624335925 839 _call_callback();
MACRUM 0:119624335925 840 }
MACRUM 0:119624335925 841 }
MACRUM 0:119624335925 842
MACRUM 0:119624335925 843 /*
MACRUM 0:119624335925 844 * Common error handler
MACRUM 0:119624335925 845 */
MACRUM 0:119624335925 846 void SPWFSAxx::_error_handler(void)
MACRUM 0:119624335925 847 {
MACRUM 0:119624335925 848 if(_parser.recv("%255[^\n]\n", _msg_buffer) && _recv_delim_lf()) {
MACRUM 0:119624335925 849 debug_if(_dbg_on, "AT^ ERROR:%s (%d)\r\n", _msg_buffer, __LINE__);
MACRUM 0:119624335925 850 } else {
MACRUM 0:119624335925 851 debug_if(_dbg_on, "\r\nSPWF> Unknown ERROR string in SPWFSAxx::_error_handler (%d)\r\n", __LINE__);
MACRUM 0:119624335925 852 }
MACRUM 0:119624335925 853
MACRUM 0:119624335925 854 /* force call of (external) callback */
MACRUM 0:119624335925 855 _call_callback();
MACRUM 0:119624335925 856 }
MACRUM 0:119624335925 857
MACRUM 0:119624335925 858 /*
MACRUM 0:119624335925 859 * Handling oob ("+WIND:33:WiFi Network Lost")
MACRUM 0:119624335925 860 */
MACRUM 0:119624335925 861 void SPWFSAxx::_network_lost_handler_th(void)
MACRUM 0:119624335925 862 {
MACRUM 0:119624335925 863 #ifndef NDEBUG
MACRUM 0:119624335925 864 static unsigned int net_loss_cnt = 0;
MACRUM 0:119624335925 865 net_loss_cnt++;
MACRUM 0:119624335925 866 #endif
MACRUM 0:119624335925 867
MACRUM 0:119624335925 868 _recv_delim_cr_lf();
MACRUM 0:119624335925 869
MACRUM 0:119624335925 870 debug_if(_dbg_on, "AT^ +WIND:33:WiFi Network Lost\r\n");
MACRUM 0:119624335925 871
MACRUM 0:119624335925 872 #ifndef NDEBUG
MACRUM 0:119624335925 873 debug_if(_dbg_on, "\r\nSPWF> Getting out of SPWFSAxx::_network_lost_handler_th: %d\r\n", net_loss_cnt);
MACRUM 0:119624335925 874 #else // NDEBUG
MACRUM 0:119624335925 875 debug_if(_dbg_on, "\r\nSPWF> Getting out of SPWFSAxx::_network_lost_handler_th: %d\r\n", __LINE__);
MACRUM 0:119624335925 876 #endif // NDEBUG
MACRUM 0:119624335925 877
MACRUM 0:119624335925 878 /* set flag to signal network loss */
MACRUM 0:119624335925 879 _network_lost_flag = true;
MACRUM 0:119624335925 880
MACRUM 0:119624335925 881 /* force call of (external) callback */
MACRUM 0:119624335925 882 _call_callback();
MACRUM 0:119624335925 883
MACRUM 0:119624335925 884 return;
MACRUM 0:119624335925 885 }
MACRUM 0:119624335925 886
MACRUM 0:119624335925 887 /* betzw - WORK AROUND module FW issues: split up big packages in smaller ones */
MACRUM 0:119624335925 888 void SPWFSAxx::_add_pending_packet_sz(int spwf_id, uint32_t size) {
MACRUM 0:119624335925 889 uint32_t to_add;
MACRUM 0:119624335925 890 uint32_t added = _get_cumulative_size(spwf_id);
MACRUM 0:119624335925 891
MACRUM 0:119624335925 892 if(size <= added) { // might happen due to delayed WIND delivery
MACRUM 0:119624335925 893 debug_if(_dbg_on, "\r\nSPWF> WARNING: %s failed at line #%d\r\n", __func__, __LINE__);
MACRUM 0:119624335925 894 return;
MACRUM 0:119624335925 895 }
MACRUM 0:119624335925 896
MACRUM 0:119624335925 897 for(to_add = ((size - added) > SPWFXX_SEND_RECV_PKTSIZE) ? SPWFXX_SEND_RECV_PKTSIZE : (size - added);
MACRUM 0:119624335925 898 added < size;
MACRUM 0:119624335925 899 to_add = ((size - added) > SPWFXX_SEND_RECV_PKTSIZE) ? SPWFXX_SEND_RECV_PKTSIZE : (size - added)) {
MACRUM 0:119624335925 900 _add_pending_pkt_size(spwf_id, added + to_add);
MACRUM 0:119624335925 901 added += to_add;
MACRUM 0:119624335925 902 }
MACRUM 0:119624335925 903
MACRUM 0:119624335925 904 /* force call of (external) callback */
MACRUM 0:119624335925 905 _call_callback();
MACRUM 0:119624335925 906
MACRUM 0:119624335925 907 /* set that data is pending */
MACRUM 0:119624335925 908 _set_pending_data(spwf_id);
MACRUM 0:119624335925 909 }
MACRUM 0:119624335925 910
MACRUM 0:119624335925 911 /*
MACRUM 0:119624335925 912 * Handling oob ("+WIND:55:Pending Data")
MACRUM 0:119624335925 913 */
MACRUM 0:119624335925 914 void SPWFSAxx::_packet_handler_th(void)
MACRUM 0:119624335925 915 {
MACRUM 0:119624335925 916 int internal_id, spwf_id;
MACRUM 0:119624335925 917 int amount;
MACRUM 0:119624335925 918
MACRUM 0:119624335925 919 /* parse out the socket id & amount */
MACRUM 0:119624335925 920 if (!(_parser.recv(SPWFXX_RECV_PENDING_DATA, &spwf_id, &amount) && _recv_delim_lf())) {
MACRUM 0:119624335925 921 #ifndef NDEBUG
MACRUM 0:119624335925 922 error("\r\nSPWF> SPWFSAxx::%s failed!\r\n", __func__);
MACRUM 0:119624335925 923 #endif
MACRUM 0:119624335925 924 return;
MACRUM 0:119624335925 925 }
MACRUM 0:119624335925 926
MACRUM 0:119624335925 927 debug_if(_dbg_on, "AT^ +WIND:55:Pending Data:%d:%d\r\n", spwf_id, amount);
MACRUM 0:119624335925 928
MACRUM 0:119624335925 929 /* check for the module to report a valid id */
MACRUM 0:119624335925 930 MBED_ASSERT(((unsigned int)spwf_id) < ((unsigned int)SPWFSA_SOCKET_COUNT));
MACRUM 0:119624335925 931
MACRUM 0:119624335925 932 /* set that there is pending data for socket */
MACRUM 0:119624335925 933 /* NOTE: it seems as if asynchronous indications might report not up-to-date data length values
MACRUM 0:119624335925 934 * therefore we just record the socket id without considering the `amount` of data reported!
MACRUM 0:119624335925 935 */
MACRUM 0:119624335925 936 internal_id = _associated_interface.get_internal_id(spwf_id);
MACRUM 0:119624335925 937 if(internal_id != SPWFSA_SOCKET_COUNT) {
MACRUM 0:119624335925 938 debug_if(_dbg_on, "AT^ +WIND:55:Pending Data:%d:%d - #2\r\n", spwf_id, amount);
MACRUM 0:119624335925 939 _add_pending_packet_sz(spwf_id, amount);
MACRUM 0:119624335925 940
MACRUM 0:119624335925 941 MBED_ASSERT(_get_pending_pkt_size(spwf_id) != 0);
MACRUM 0:119624335925 942 } else {
MACRUM 0:119624335925 943 debug_if(_dbg_on, "\r\nSPWFSAxx::%s got invalid id %d\r\n", __func__, spwf_id);
MACRUM 0:119624335925 944 }
MACRUM 0:119624335925 945 }
MACRUM 0:119624335925 946
MACRUM 0:119624335925 947 void SPWFSAxx::_network_lost_handler_bh(void)
MACRUM 0:119624335925 948 {
MACRUM 0:119624335925 949 if(!_network_lost_flag) return;
MACRUM 0:119624335925 950 _network_lost_flag = false;
MACRUM 0:119624335925 951
MACRUM 0:119624335925 952 {
MACRUM 0:119624335925 953 bool were_connected;
MACRUM 0:119624335925 954 BlockExecuter netsock_wa_obj(Callback<void()>(this, &SPWFSAxx::_unblock_event_callback),
MACRUM 0:119624335925 955 Callback<void()>(this, &SPWFSAxx::_block_event_callback)); /* do not call (external) callback in IRQ context as long as network is lost */
MACRUM 0:119624335925 956 Timer timer;
MACRUM 0:119624335925 957 timer.start();
MACRUM 0:119624335925 958
MACRUM 0:119624335925 959 _parser.set_timeout(SPWF_NETLOST_TIMEOUT);
MACRUM 0:119624335925 960
MACRUM 0:119624335925 961 were_connected = isConnected();
MACRUM 0:119624335925 962 _associated_interface._connected_to_network = false;
MACRUM 0:119624335925 963
MACRUM 0:119624335925 964 if(were_connected) {
MACRUM 0:119624335925 965 unsigned int n1, n2, n3, n4;
MACRUM 0:119624335925 966
MACRUM 0:119624335925 967 while(true) {
MACRUM 0:119624335925 968 if (timer.read_ms() > SPWF_CONNECT_TIMEOUT) {
MACRUM 0:119624335925 969 debug_if(_dbg_on, "\r\nSPWF> SPWFSAxx::_network_lost_handler_bh() #%d\r\n", __LINE__);
MACRUM 0:119624335925 970 disconnect();
MACRUM 0:119624335925 971 empty_rx_buffer();
MACRUM 0:119624335925 972 goto nlh_get_out;
MACRUM 0:119624335925 973 }
MACRUM 0:119624335925 974
MACRUM 0:119624335925 975 if((_parser.recv(SPWFXX_RECV_WIFI_UP, &n1, &n2, &n3, &n4)) && _recv_delim_lf()) {
MACRUM 0:119624335925 976 debug_if(_dbg_on, "\r\nSPWF> Re-connected (%u.%u.%u.%u)!\r\n", n1, n2, n3, n4);
MACRUM 0:119624335925 977
MACRUM 0:119624335925 978 _associated_interface._connected_to_network = true;
MACRUM 0:119624335925 979 goto nlh_get_out;
MACRUM 0:119624335925 980 }
MACRUM 0:119624335925 981 }
MACRUM 0:119624335925 982 } else {
MACRUM 0:119624335925 983 debug_if(_dbg_on, "\r\nSPWF> Leaving SPWFSAxx::_network_lost_handler_bh\r\n");
MACRUM 0:119624335925 984 goto nlh_get_out;
MACRUM 0:119624335925 985 }
MACRUM 0:119624335925 986
MACRUM 0:119624335925 987 nlh_get_out:
MACRUM 0:119624335925 988 debug_if(_dbg_on, "\r\nSPWF> Getting out of SPWFSAxx::_network_lost_handler_bh\r\n");
MACRUM 0:119624335925 989 _parser.set_timeout(_timeout);
MACRUM 0:119624335925 990
MACRUM 0:119624335925 991 /* force call of (external) callback */
MACRUM 0:119624335925 992 _call_callback();
MACRUM 0:119624335925 993
MACRUM 0:119624335925 994 return;
MACRUM 0:119624335925 995 }
MACRUM 0:119624335925 996 }
MACRUM 0:119624335925 997
MACRUM 0:119624335925 998 void SPWFSAxx::_recover_from_hard_faults(void) {
MACRUM 0:119624335925 999 disconnect();
MACRUM 0:119624335925 1000 empty_rx_buffer();
MACRUM 0:119624335925 1001
MACRUM 0:119624335925 1002 /* force call of (external) callback */
MACRUM 0:119624335925 1003 _call_callback();
MACRUM 0:119624335925 1004 }
MACRUM 0:119624335925 1005
MACRUM 0:119624335925 1006 /*
MACRUM 0:119624335925 1007 * Handling oob ("+WIND:8:Hard Fault")
MACRUM 0:119624335925 1008 */
MACRUM 0:119624335925 1009 void SPWFSAxx::_hard_fault_handler(void)
MACRUM 0:119624335925 1010 {
MACRUM 0:119624335925 1011 _parser.set_timeout(SPWF_RECV_TIMEOUT);
MACRUM 0:119624335925 1012 if(_parser.recv("%255[^\n]\n", _msg_buffer) && _recv_delim_lf()) {
MACRUM 0:119624335925 1013 #ifndef NDEBUG
MACRUM 0:119624335925 1014 error("\r\nSPWF> hard fault error:\r\n%s\r\n", _msg_buffer);
MACRUM 0:119624335925 1015 #else // NDEBUG
MACRUM 0:119624335925 1016 debug("\r\nSPWF> hard fault error:\r\n%s\r\n", _msg_buffer);
MACRUM 0:119624335925 1017 #endif // NDEBUG
MACRUM 0:119624335925 1018 } else {
MACRUM 0:119624335925 1019 #ifndef NDEBUG
MACRUM 0:119624335925 1020 error("\r\nSPWF> unknown hard fault error\r\n");
MACRUM 0:119624335925 1021 #else // NDEBUG
MACRUM 0:119624335925 1022 debug("\r\nSPWF> unknown hard fault error\r\n");
MACRUM 0:119624335925 1023 #endif // NDEBUG
MACRUM 0:119624335925 1024 }
MACRUM 0:119624335925 1025
MACRUM 0:119624335925 1026 // This is most likely the best we can do to recover from this module hard fault
MACRUM 0:119624335925 1027 _parser.set_timeout(SPWF_HF_TIMEOUT);
MACRUM 0:119624335925 1028 _recover_from_hard_faults();
MACRUM 0:119624335925 1029 _parser.set_timeout(_timeout);
MACRUM 0:119624335925 1030
MACRUM 0:119624335925 1031 /* force call of (external) callback */
MACRUM 0:119624335925 1032 _call_callback();
MACRUM 0:119624335925 1033 }
MACRUM 0:119624335925 1034
MACRUM 0:119624335925 1035 /*
MACRUM 0:119624335925 1036 * Handling oob ("+WIND:5:WiFi Hardware Failure")
MACRUM 0:119624335925 1037 */
MACRUM 0:119624335925 1038 void SPWFSAxx::_wifi_hwfault_handler(void)
MACRUM 0:119624335925 1039 {
MACRUM 0:119624335925 1040 unsigned int failure_nr;
MACRUM 0:119624335925 1041
MACRUM 0:119624335925 1042 /* parse out the socket id & amount */
MACRUM 0:119624335925 1043 _parser.recv(":%u\n", &failure_nr);
MACRUM 0:119624335925 1044 _recv_delim_lf();
MACRUM 0:119624335925 1045
MACRUM 0:119624335925 1046 #ifndef NDEBUG
MACRUM 0:119624335925 1047 error("\r\nSPWF> WiFi HW fault error: %u\r\n", failure_nr);
MACRUM 0:119624335925 1048 #else // NDEBUG
MACRUM 0:119624335925 1049 debug("\r\nSPWF> WiFi HW fault error: %u\r\n", failure_nr);
MACRUM 0:119624335925 1050
MACRUM 0:119624335925 1051 // This is most likely the best we can do to recover from this module hard fault
MACRUM 0:119624335925 1052 _parser.set_timeout(SPWF_HF_TIMEOUT);
MACRUM 0:119624335925 1053 _recover_from_hard_faults();
MACRUM 0:119624335925 1054 _parser.set_timeout(_timeout);
MACRUM 0:119624335925 1055 #endif // NDEBUG
MACRUM 0:119624335925 1056
MACRUM 0:119624335925 1057 /* force call of (external) callback */
MACRUM 0:119624335925 1058 _call_callback();
MACRUM 0:119624335925 1059 }
MACRUM 0:119624335925 1060
MACRUM 0:119624335925 1061 /*
MACRUM 0:119624335925 1062 * Handling oob ("+WIND:58:Socket Closed")
MACRUM 0:119624335925 1063 * when server closes a client connection
MACRUM 0:119624335925 1064 *
MACRUM 0:119624335925 1065 * NOTE: When a socket client receives an indication about socket server gone (only for TCP sockets, WIND:58),
MACRUM 0:119624335925 1066 * the socket connection is NOT automatically closed!
MACRUM 0:119624335925 1067 */
MACRUM 0:119624335925 1068 void SPWFSAxx::_server_gone_handler(void)
MACRUM 0:119624335925 1069 {
MACRUM 0:119624335925 1070 int spwf_id, internal_id;
MACRUM 0:119624335925 1071
MACRUM 0:119624335925 1072 if(!(_parser.recv(SPWFXX_RECV_SOCKET_CLOSED, &spwf_id) && _recv_delim_lf())) {
MACRUM 0:119624335925 1073 #ifndef NDEBUG
MACRUM 0:119624335925 1074 error("\r\nSPWF> SPWFSAxx::%s failed!\r\n", __func__);
MACRUM 0:119624335925 1075 #endif
MACRUM 0:119624335925 1076 goto _get_out;
MACRUM 0:119624335925 1077 }
MACRUM 0:119624335925 1078
MACRUM 0:119624335925 1079 debug_if(_dbg_on, "AT^ +WIND:58:Socket Closed:%d\r\n", spwf_id);
MACRUM 0:119624335925 1080
MACRUM 0:119624335925 1081 /* check for the module to report a valid id */
MACRUM 0:119624335925 1082 MBED_ASSERT(((unsigned int)spwf_id) < ((unsigned int)SPWFSA_SOCKET_COUNT));
MACRUM 0:119624335925 1083
MACRUM 0:119624335925 1084 /* only set `server_gone`
MACRUM 0:119624335925 1085 * user still can receive data & must still explicitly close the socket
MACRUM 0:119624335925 1086 */
MACRUM 0:119624335925 1087 internal_id = _associated_interface.get_internal_id(spwf_id);
MACRUM 0:119624335925 1088 if(internal_id != SPWFSA_SOCKET_COUNT) {
MACRUM 0:119624335925 1089 _associated_interface._ids[internal_id].server_gone = true;
MACRUM 0:119624335925 1090 }
MACRUM 0:119624335925 1091
MACRUM 0:119624335925 1092 _get_out:
MACRUM 0:119624335925 1093 /* force call of (external) callback */
MACRUM 0:119624335925 1094 _call_callback();
MACRUM 0:119624335925 1095 }
MACRUM 0:119624335925 1096
MACRUM 0:119624335925 1097 #if MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1
MACRUM 0:119624335925 1098 /*
MACRUM 0:119624335925 1099 * Handling oob (currently only for "+WIND:24:WiFi Up::")
MACRUM 0:119624335925 1100 */
MACRUM 0:119624335925 1101 void SPWFSAxx::_skip_oob(void)
MACRUM 0:119624335925 1102 {
MACRUM 0:119624335925 1103 if(_parser.recv("%255[^\n]\n", _msg_buffer) && _recv_delim_lf()) {
MACRUM 0:119624335925 1104 debug_if(_dbg_on, "AT^ +WIND:24:WiFi Up::%s\r\n", _msg_buffer);
MACRUM 0:119624335925 1105 } else {
MACRUM 0:119624335925 1106 debug_if(_dbg_on, "\r\nSPWF> Invalid string in SPWFSAxx::_skip_oob (%d)\r\n", __LINE__);
MACRUM 0:119624335925 1107 }
MACRUM 0:119624335925 1108 }
MACRUM 0:119624335925 1109 #endif
MACRUM 0:119624335925 1110
MACRUM 0:119624335925 1111 void SPWFSAxx::setTimeout(uint32_t timeout_ms)
MACRUM 0:119624335925 1112 {
MACRUM 0:119624335925 1113 _timeout = timeout_ms;
MACRUM 0:119624335925 1114 _parser.set_timeout(timeout_ms);
MACRUM 0:119624335925 1115 }
MACRUM 0:119624335925 1116
MACRUM 0:119624335925 1117 void SPWFSAxx::attach(Callback<void()> func)
MACRUM 0:119624335925 1118 {
MACRUM 0:119624335925 1119 _callback_func = func; /* do not call (external) callback in IRQ context during critical module operations */
MACRUM 0:119624335925 1120 }
MACRUM 0:119624335925 1121
MACRUM 0:119624335925 1122 /**
MACRUM 0:119624335925 1123 * Recv Function
MACRUM 0:119624335925 1124 */
MACRUM 0:119624335925 1125 int32_t SPWFSAxx::recv(int spwf_id, void *data, uint32_t amount, bool datagram)
MACRUM 0:119624335925 1126 {
MACRUM 0:119624335925 1127 BlockExecuter bh_handler(Callback<void()>(this, &SPWFSAxx::_execute_bottom_halves));
MACRUM 0:119624335925 1128
MACRUM 0:119624335925 1129 while (true) {
MACRUM 0:119624335925 1130 /* check if any packets are ready for us */
MACRUM 0:119624335925 1131 for (struct packet **p = &_packets; *p; p = &(*p)->next) {
MACRUM 0:119624335925 1132 if ((*p)->id == spwf_id) {
MACRUM 0:119624335925 1133 debug_if(_dbg_on, "\r\nSPWF> Read done on ID %d and length of packet is %d\r\n",spwf_id,(*p)->len);
MACRUM 0:119624335925 1134 struct packet *q = *p;
MACRUM 0:119624335925 1135
MACRUM 0:119624335925 1136 MBED_ASSERT(q->len > 0);
MACRUM 0:119624335925 1137
MACRUM 0:119624335925 1138 if(datagram) { // UDP => always remove pkt size
MACRUM 0:119624335925 1139 // will always consume a whole pending size
MACRUM 0:119624335925 1140 uint32_t ret;
MACRUM 0:119624335925 1141
MACRUM 0:119624335925 1142 debug_if(_dbg_on, "\r\nSPWF> %s():\t\t\t%d:%d (datagram)\r\n", __func__, spwf_id, q->len);
MACRUM 0:119624335925 1143
MACRUM 0:119624335925 1144 ret = (amount < q->len) ? amount : q->len;
MACRUM 0:119624335925 1145 memcpy(data, q+1, ret);
MACRUM 0:119624335925 1146
MACRUM 0:119624335925 1147 if (_packets_end == &(*p)->next) {
MACRUM 0:119624335925 1148 _packets_end = p;
MACRUM 0:119624335925 1149 }
MACRUM 0:119624335925 1150 *p = (*p)->next;
MACRUM 0:119624335925 1151 free(q);
MACRUM 0:119624335925 1152
MACRUM 0:119624335925 1153 return ret;
MACRUM 0:119624335925 1154 } else { // TCP
MACRUM 0:119624335925 1155 if (q->len <= amount) { // return and remove full packet
MACRUM 0:119624335925 1156 memcpy(data, q+1, q->len);
MACRUM 0:119624335925 1157
MACRUM 0:119624335925 1158 if (_packets_end == &(*p)->next) {
MACRUM 0:119624335925 1159 _packets_end = p;
MACRUM 0:119624335925 1160 }
MACRUM 0:119624335925 1161 *p = (*p)->next;
MACRUM 0:119624335925 1162 uint32_t len = q->len;
MACRUM 0:119624335925 1163 free(q);
MACRUM 0:119624335925 1164
MACRUM 0:119624335925 1165 return len;
MACRUM 0:119624335925 1166 } else { // `q->len > amount`, return only partial packet
MACRUM 0:119624335925 1167 if(amount > 0) {
MACRUM 0:119624335925 1168 memcpy(data, q+1, amount);
MACRUM 0:119624335925 1169 q->len -= amount;
MACRUM 0:119624335925 1170 memmove(q+1, (uint8_t*)(q+1) + amount, q->len);
MACRUM 0:119624335925 1171 }
MACRUM 0:119624335925 1172
MACRUM 0:119624335925 1173 return amount;
MACRUM 0:119624335925 1174 }
MACRUM 0:119624335925 1175 }
MACRUM 0:119624335925 1176 }
MACRUM 0:119624335925 1177 }
MACRUM 0:119624335925 1178
MACRUM 0:119624335925 1179 /* check for pending data on module */
MACRUM 0:119624335925 1180 {
MACRUM 0:119624335925 1181 int len;
MACRUM 0:119624335925 1182
MACRUM 0:119624335925 1183 len = _read_in_pkt(spwf_id, false);
MACRUM 0:119624335925 1184 if(len <= 0) { /* SPWFXX error or no more data to be read */
MACRUM 0:119624335925 1185 return -1;
MACRUM 0:119624335925 1186 }
MACRUM 0:119624335925 1187 }
MACRUM 0:119624335925 1188 }
MACRUM 0:119624335925 1189 }
MACRUM 0:119624335925 1190
MACRUM 0:119624335925 1191 void SPWFSAxx::_process_winds(void) {
MACRUM 0:119624335925 1192 do {
MACRUM 0:119624335925 1193 if(_parser.process_oob()) {
MACRUM 0:119624335925 1194 /* nothing else to do! */;
MACRUM 0:119624335925 1195 } else {
MACRUM 0:119624335925 1196 debug_if(_dbg_on, "%s():\t\tNo (more) oob's found!\r\n", __func__);
MACRUM 0:119624335925 1197 return; // no (more) oob's found
MACRUM 0:119624335925 1198 }
MACRUM 0:119624335925 1199 } while(true);
MACRUM 0:119624335925 1200 }
MACRUM 0:119624335925 1201
MACRUM 0:119624335925 1202 /* Note: returns
MACRUM 0:119624335925 1203 * '>=0' in case of success, amount of read in data (in bytes)
MACRUM 0:119624335925 1204 * 'SPWFXX_ERR_OOM' in case of "out of memory"
MACRUM 0:119624335925 1205 * 'SPWFXX_ERR_READ' in case of other `_read_in_packet()` error
MACRUM 0:119624335925 1206 * 'SPWFXX_ERR_LEN' in case of `_read_len()` error
MACRUM 0:119624335925 1207 */
MACRUM 0:119624335925 1208 int SPWFSAxx::_read_in_pkt(int spwf_id, bool close) {
MACRUM 0:119624335925 1209 int pending;
MACRUM 0:119624335925 1210 uint32_t wind_pending;
MACRUM 0:119624335925 1211 BlockExecuter netsock_wa_obj(Callback<void()>(this, &SPWFSAxx::_unblock_event_callback),
MACRUM 0:119624335925 1212 Callback<void()>(this, &SPWFSAxx::_block_event_callback)); /* do not call (external) callback in IRQ context while receiving */
MACRUM 0:119624335925 1213
MACRUM 0:119624335925 1214 _process_winds(); // perform async indication handling
MACRUM 0:119624335925 1215
MACRUM 0:119624335925 1216 if(close) { // read in all data
MACRUM 0:119624335925 1217 wind_pending = pending = _read_len(spwf_id); // triggers also async indication handling!
MACRUM 0:119624335925 1218
MACRUM 0:119624335925 1219 if(pending > 0) {
MACRUM 0:119624335925 1220 /* reset pending data sizes */
MACRUM 0:119624335925 1221 _reset_pending_pkt_sizes(spwf_id);
MACRUM 0:119624335925 1222 /* create new entry for pending size */
MACRUM 0:119624335925 1223 _add_pending_pkt_size(spwf_id, (uint32_t)pending);
MACRUM 0:119624335925 1224 #ifndef NDEBUG
MACRUM 0:119624335925 1225 wind_pending = _get_pending_pkt_size(spwf_id);
MACRUM 0:119624335925 1226 MBED_ASSERT(pending == (int)wind_pending);
MACRUM 0:119624335925 1227 #endif
MACRUM 0:119624335925 1228 } else if(pending < 0) {
MACRUM 0:119624335925 1229 debug_if(_dbg_on, "\r\nSPWF> %s(), #%d:`_read_len()` failed (%d)!\r\n", __func__, __LINE__, pending);
MACRUM 0:119624335925 1230 }
MACRUM 0:119624335925 1231 } else { // only read in already notified data
MACRUM 0:119624335925 1232 pending = wind_pending = _get_pending_pkt_size(spwf_id);
MACRUM 0:119624335925 1233 if(pending == 0) { // special handling for no packets pending (to WORK AROUND missing WINDs)!
MACRUM 0:119624335925 1234 pending = _read_len(spwf_id); // triggers also async indication handling!
MACRUM 0:119624335925 1235
MACRUM 0:119624335925 1236 if(pending > 0) {
MACRUM 0:119624335925 1237 _process_winds(); // perform async indication handling (again)
MACRUM 0:119624335925 1238 wind_pending = _get_pending_pkt_size(spwf_id);
MACRUM 0:119624335925 1239
MACRUM 0:119624335925 1240 if(wind_pending == 0) {
MACRUM 0:119624335925 1241 /* betzw - WORK AROUND module FW issues: create new entry for pending size */
MACRUM 0:119624335925 1242 debug_if(_dbg_on, "%s():\t\tAdd packet w/o WIND (%d)!\r\n", __func__, pending);
MACRUM 0:119624335925 1243 _add_pending_packet_sz(spwf_id, (uint32_t)pending);
MACRUM 0:119624335925 1244
MACRUM 0:119624335925 1245 pending = wind_pending = _get_pending_pkt_size(spwf_id);
MACRUM 0:119624335925 1246 MBED_ASSERT(wind_pending > 0);
MACRUM 0:119624335925 1247 }
MACRUM 0:119624335925 1248 } else if(pending < 0) {
MACRUM 0:119624335925 1249 debug_if(_dbg_on, "\r\nSPWF> %s(), #%d:`_read_len()` failed (%d)!\r\n", __func__, __LINE__, pending);
MACRUM 0:119624335925 1250 }
MACRUM 0:119624335925 1251 }
MACRUM 0:119624335925 1252 }
MACRUM 0:119624335925 1253
MACRUM 0:119624335925 1254 if((pending > 0) && (wind_pending > 0)) {
MACRUM 0:119624335925 1255 int ret = _read_in_packet(spwf_id, wind_pending);
MACRUM 0:119624335925 1256 if(ret < 0) { /* "out of memory" or `_read_in_packet()` error */
MACRUM 0:119624335925 1257 /* we do not know if data is still pending at this point
MACRUM 0:119624335925 1258 but leaving the pending data bit set might lead to an endless loop */
MACRUM 0:119624335925 1259 _clear_pending_data(spwf_id);
MACRUM 0:119624335925 1260 /* also reset pending data sizes */
MACRUM 0:119624335925 1261 _reset_pending_pkt_sizes(spwf_id);
MACRUM 0:119624335925 1262
MACRUM 0:119624335925 1263 return ret;
MACRUM 0:119624335925 1264 }
MACRUM 0:119624335925 1265
MACRUM 0:119624335925 1266 if((_get_cumulative_size(spwf_id) == 0) && (pending <= (int)wind_pending)) {
MACRUM 0:119624335925 1267 _clear_pending_data(spwf_id);
MACRUM 0:119624335925 1268 }
MACRUM 0:119624335925 1269 } else if(pending < 0) { /* 'SPWFXX_ERR_LEN' error */
MACRUM 0:119624335925 1270 MBED_ASSERT(pending == SPWFXX_ERR_LEN);
MACRUM 0:119624335925 1271 /* we do not know if data is still pending at this point
MACRUM 0:119624335925 1272 but leaving the pending data bit set might lead to an endless loop */
MACRUM 0:119624335925 1273 _clear_pending_data(spwf_id);
MACRUM 0:119624335925 1274 /* also reset pending data sizes */
MACRUM 0:119624335925 1275 _reset_pending_pkt_sizes(spwf_id);
MACRUM 0:119624335925 1276
MACRUM 0:119624335925 1277 return pending;
MACRUM 0:119624335925 1278 } else if(pending == 0) {
MACRUM 0:119624335925 1279 MBED_ASSERT(wind_pending == 0);
MACRUM 0:119624335925 1280 _clear_pending_data(spwf_id);
MACRUM 0:119624335925 1281 } else if(wind_pending == 0) { // `pending > 0`
MACRUM 0:119624335925 1282 /* betzw: should never happen! */
MACRUM 0:119624335925 1283 MBED_ASSERT(false);
MACRUM 0:119624335925 1284 }
MACRUM 0:119624335925 1285
MACRUM 0:119624335925 1286 return (int)wind_pending;
MACRUM 0:119624335925 1287 }