Generic Pelion Device Management example for various Advantech modules.
This example is known to work great on the following platforms:
- WISE-1530 WiFi Module using DB-1505 carrier board and external SD card reader.
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.
drivers/network/COMPONENT_WIFI_IDW04A1/SPWFSAxx.cpp@0:43ff9e3bc244, 2019-03-12 (annotated)
- 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?
User | Revision | Line number | New 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 | } |