wifi test

Dependencies:   X_NUCLEO_IKS01A2 mbed-http

Committer:
JMF
Date:
Wed Sep 05 14:28:24 2018 +0000
Revision:
0:24d3eb812fd4
Initial commit

Who changed what in which revision?

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