test

Dependents:   mbed-os-example-blinky-1stDevDemo

Committer:
karen801
Date:
Wed May 23 14:37:10 2018 +0000
Revision:
0:79ce2b184a43
Initial commit

Who changed what in which revision?

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