Generic Pelion Device Management example for various Advantech modules.

This example is known to work great on the following platforms:

Example Functionality

This example showcases the following device functionality:

  • On timer button increment, simulate Pelion LWM2M button resource change

Use this example with Mbed CLI

1. Import the application into your desktop:

mbed import https://os.mbed.com/teams/Advantech/code/pelion-example-common
cd pelion-example-common

2. Download your developer certificate from pelion portal

3. Compile the program

mbed compile -t <toolchain> -m <TARGET_BOARD>

(supported toolchains : GCC_ARM / ARM / IAR)

4. Copy the binary file pelion-example-common.bin to your mbed device.

Committer:
chuanga
Date:
Tue Mar 12 13:48:39 2019 +0800
Revision:
0:43ff9e3bc244
copying sources from github repository

Who changed what in which revision?

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