Toyomasa Watarai
/
Mbed-example-WS-W27
Mbed Cloud example program for workshop in W27 2018.
Embed:
(wiki syntax)
Show/hide line numbers
SPWFSAxx.cpp
00001 /* SPWFSAxx Devices 00002 * Copyright (c) 2015 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #include "mbed_debug.h" 00018 00019 #include "SpwfSAInterface.h" /* must be included first */ 00020 #include "SPWFSAxx.h" 00021 00022 static const char out_delim[] = {SPWFSAxx::_cr_, '\0'}; 00023 00024 SPWFSAxx::SPWFSAxx(PinName tx, PinName rx, 00025 PinName rts, PinName cts, 00026 SpwfSAInterface &ifce, bool debug, 00027 PinName wakeup, PinName reset) 00028 : _serial(tx, rx, SPWFXX_DEFAULT_BAUD_RATE), _parser(&_serial, out_delim), 00029 _wakeup(wakeup, 1), _reset(reset, 1), 00030 _rts(rts), _cts(cts), 00031 _timeout(SPWF_INIT_TIMEOUT), _dbg_on(debug), 00032 _pending_sockets_bitmap(0), 00033 _network_lost_flag(false), 00034 _associated_interface(ifce), 00035 _call_event_callback_blocked(0), 00036 _callback_func(), 00037 _packets(0), _packets_end(&_packets) 00038 { 00039 memset(_pending_pkt_sizes, 0, sizeof(_pending_pkt_sizes)); 00040 00041 _serial.sigio(Callback<void()>(this, &SPWFSAxx::_event_handler)); 00042 _parser.debug_on(debug); 00043 _parser.set_timeout(_timeout); 00044 00045 /* unlikely OOBs */ 00046 _parser.oob("+WIND:5:WiFi Hardware Failure", callback(this, &SPWFSAxx::_wifi_hwfault_handler)); 00047 _parser.oob("+WIND:33:WiFi Network Lost", callback(this, &SPWFSAxx::_network_lost_handler_th)); 00048 #if MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1 00049 _parser.oob("+WIND:24:WiFi Up::", callback(this, &SPWFSAxx::_skip_oob)); 00050 #endif 00051 _parser.oob("+WIND:8:Hard Fault", callback(this, &SPWFSAxx::_hard_fault_handler)); 00052 00053 /* most likely OOBs */ 00054 _parser.oob(SPWFXX_OOB_ERROR, callback(this, &SPWFSAxx::_error_handler)); 00055 _parser.oob("+WIND:58:Socket Closed", callback(this, &SPWFSAxx::_server_gone_handler)); 00056 _parser.oob("+WIND:55:Pending Data", callback(this, &SPWFSAxx::_packet_handler_th)); 00057 } 00058 00059 bool SPWFSAxx::startup(int mode) 00060 { 00061 BlockExecuter netsock_wa_obj(Callback<void()>(this, &SPWFSAxx::_unblock_event_callback), 00062 Callback<void()>(this, &SPWFSAxx::_block_event_callback)); /* disable calling (external) callback in IRQ context */ 00063 00064 /*Reset module*/ 00065 if(!hw_reset()) { 00066 debug_if(_dbg_on, "\r\nSPWF> HW reset failed\r\n"); 00067 return false; 00068 } 00069 00070 /* factory reset */ 00071 if(!(_parser.send(SPWFXX_SEND_FWCFG) && _recv_ok())) 00072 { 00073 debug_if(_dbg_on, "\r\nSPWF> error restore factory default settings\r\n"); 00074 return false; 00075 } 00076 00077 /*switch off led*/ 00078 if(!(_parser.send("AT+S.SCFG=blink_led,0") && _recv_ok())) 00079 { 00080 debug_if(_dbg_on, "\r\nSPWF> error stop blinking led (%d)\r\n", __LINE__); 00081 return false; 00082 } 00083 00084 /*set local echo to 0*/ 00085 if(!(_parser.send(SPWFXX_SEND_DISABLE_LE) && _recv_ok())) 00086 { 00087 debug_if(_dbg_on, "\r\nSPWF> error local echo set\r\n"); 00088 return false; 00089 } 00090 00091 /*set the operational rates*/ 00092 if(!(_parser.send("AT+S.SCFG=wifi_opr_rate_mask,0x003FFFCF") && _recv_ok())) 00093 { 00094 debug_if(_dbg_on, "\r\nSPWF> error setting ht_mode\r\n"); 00095 return false; 00096 } 00097 00098 /*enable the 802.11n mode*/ 00099 if(!(_parser.send("AT+S.SCFG=wifi_ht_mode,1") && _recv_ok())) 00100 { 00101 debug_if(_dbg_on, "\r\nSPWF> error setting operational rates\r\n"); 00102 return false; 00103 } 00104 00105 /*set idle mode (0->idle, 1->STA,3->miniAP, 2->IBSS)*/ 00106 if(!(_parser.send("AT+S.SCFG=wifi_mode,%d", mode) && _recv_ok())) 00107 { 00108 debug_if(_dbg_on, "\r\nSPWF> error WiFi mode set idle (%d)\r\n", __LINE__); 00109 return false; 00110 } 00111 00112 #if defined(MBED_MAJOR_VERSION) 00113 #if !DEVICE_SERIAL_FC || (MBED_VERSION < MBED_ENCODE_VERSION(5, 7, 0)) 00114 /*disable HW flow control*/ 00115 if(!(_parser.send(SPWFXX_SEND_DISABLE_FC) && _recv_ok())) 00116 { 00117 debug_if(_dbg_on, "\r\nSPWF> error disabling HW flow control\r\n"); 00118 return false; 00119 } 00120 #else // DEVICE_SERIAL_FC && (MBED_VERSION >= MBED_ENCODE_VERSION(5, 7, 0)) 00121 if((_rts != NC) && (_cts != NC)) { 00122 /*enable HW flow control*/ 00123 if(!(_parser.send(SPWFXX_SEND_ENABLE_FC) && _recv_ok())) 00124 { 00125 debug_if(_dbg_on, "\r\nSPWF> error enabling HW flow control\r\n"); 00126 return false; 00127 } 00128 00129 /*configure pins for HW flow control*/ 00130 _serial.set_flow_control(SerialBase::RTSCTS, _rts, _cts); 00131 } else { 00132 /*disable HW flow control*/ 00133 if(!(_parser.send(SPWFXX_SEND_DISABLE_FC) && _recv_ok())) 00134 { 00135 debug_if(_dbg_on, "\r\nSPWF> error disabling HW flow control\r\n"); 00136 return false; 00137 } 00138 } 00139 #endif // DEVICE_SERIAL_FC && (MBED_VERSION >= MBED_ENCODE_VERSION(5, 7, 0)) 00140 #else // !defined(MBED_MAJOR_VERSION) - Assuming `master` branch 00141 #if !DEVICE_SERIAL_FC 00142 /*disable HW flow control*/ 00143 if(!(_parser.send(SPWFXX_SEND_DISABLE_FC) && _recv_ok())) 00144 { 00145 debug_if(_dbg_on, "\r\nSPWF> error disabling HW flow control\r\n"); 00146 return false; 00147 } 00148 #else // DEVICE_SERIAL_FC 00149 if((_rts != NC) && (_cts != NC)) { 00150 /*enable HW flow control*/ 00151 if(!(_parser.send(SPWFXX_SEND_ENABLE_FC) && _recv_ok())) 00152 { 00153 debug_if(_dbg_on, "\r\nSPWF> error enabling HW flow control\r\n"); 00154 return false; 00155 } 00156 00157 /*configure pins for HW flow control*/ 00158 _serial.set_flow_control(SerialBase::RTSCTS, _rts, _cts); 00159 } else { 00160 /*disable HW flow control*/ 00161 if(!(_parser.send(SPWFXX_SEND_DISABLE_FC) && _recv_ok())) 00162 { 00163 debug_if(_dbg_on, "\r\nSPWF> error disabling HW flow control\r\n"); 00164 return false; 00165 } 00166 } 00167 #endif // DEVICE_SERIAL_FC 00168 #endif // !defined(MBED_MAJOR_VERSION) 00169 00170 /* Disable selected WINDs */ 00171 _winds_on(); 00172 00173 /* sw reset */ 00174 if(!reset()) { 00175 debug_if(_dbg_on, "\r\nSPWF> SW reset failed (%s, %d)\r\n", __func__, __LINE__); 00176 return false; 00177 } 00178 00179 #ifndef NDEBUG 00180 if (!(_parser.send(SPWFXX_SEND_GET_CONS_STATE) 00181 && _recv_ok())) { 00182 debug_if(_dbg_on, "\r\nSPWF> error getting console state\r\n"); 00183 return false; 00184 } 00185 00186 if (!(_parser.send(SPWFXX_SEND_GET_CONS_SPEED) 00187 && _recv_ok())) { 00188 debug_if(_dbg_on, "\r\nSPWF> error getting console speed\r\n"); 00189 return false; 00190 } 00191 00192 if (!(_parser.send(SPWFXX_SEND_GET_HWFC_STATE) 00193 && _recv_ok())) { 00194 debug_if(_dbg_on, "\r\nSPWF> error getting hwfc state\r\n"); 00195 return false; 00196 } 00197 00198 #if (MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1) || defined(IDW01M1_FW_REL_35X) 00199 /* betzw: IDW01M1 FW versions <3.5 seem to have problems with the following two commands. 00200 * For the sake of simplicity, just excluding them for IDW01M1 in general. 00201 */ 00202 if (!(_parser.send(SPWFXX_SEND_GET_CONS_DELIM) 00203 && _recv_ok())) { 00204 debug_if(_dbg_on, "\r\nSPWF> error getting console delimiter\r\n"); 00205 return false; 00206 } 00207 00208 if (!(_parser.send(SPWFXX_SEND_GET_CONS_ERRS) 00209 && _recv_ok())) { 00210 debug_if(_dbg_on, "\r\nSPWF> error getting console error setting\r\n"); 00211 return false; 00212 } 00213 #endif // (MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1) || defined(IDW01M1_FW_REL_35X) 00214 00215 if (!(_parser.send("AT+S.GCFG=sleep_enabled") 00216 && _recv_ok())) { 00217 debug_if(_dbg_on, "\r\nSPWF> error getting sleep state enabled\r\n"); 00218 return false; 00219 } 00220 00221 if (!(_parser.send("AT+S.GCFG=wifi_powersave") 00222 && _recv_ok())) { 00223 debug_if(_dbg_on, "\r\nSPWF> error getting powersave mode\r\n"); 00224 return false; 00225 } 00226 00227 if (!(_parser.send("AT+S.GCFG=standby_enabled") 00228 && _recv_ok())) { 00229 debug_if(_dbg_on, "\r\nSPWF> error getting standby state enabled\r\n"); 00230 return false; 00231 } 00232 #endif 00233 00234 return true; 00235 } 00236 00237 bool SPWFSAxx::_wait_console_active(void) { 00238 int trials = 0; 00239 00240 while(true) { 00241 if (_parser.recv("+WIND:0:Console active\n") && _recv_delim_lf()) { 00242 debug_if(_dbg_on, "AT^ +WIND:0:Console active\r\n"); 00243 return true; 00244 } 00245 if(++trials >= SPWFXX_MAX_TRIALS) { 00246 debug("\r\nSPWF> ERROR: Should never happen! (%s, %d)\r\n", __func__, __LINE__); 00247 empty_rx_buffer(); 00248 return false; 00249 } 00250 } 00251 } 00252 00253 bool SPWFSAxx::_wait_wifi_hw_started(void) { 00254 int trials = 0; 00255 00256 while(true) { 00257 if (_parser.recv("+WIND:32:WiFi Hardware Started\n") && _recv_delim_lf()) { 00258 debug_if(_dbg_on, "AT^ +WIND:32:WiFi Hardware Started\r\n"); 00259 return true; 00260 } 00261 if(++trials >= SPWFXX_MAX_TRIALS) { 00262 debug("\r\nSPWF> ERROR: Should never happen! (%s, %d)\r\n", __func__, __LINE__); 00263 empty_rx_buffer(); 00264 return false; 00265 } 00266 } 00267 } 00268 00269 bool SPWFSAxx::hw_reset(void) 00270 { 00271 #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 00272 _reset.write(0); 00273 wait_ms(200); 00274 _reset.write(1); 00275 #else // (MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1) && defined(IDW04A1_WIFI_HW_BUG_WA): substitute with SW reset 00276 _parser.send(SPWFXX_SEND_SW_RESET); 00277 #endif // (MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1) && defined(IDW04A1_WIFI_HW_BUG_WA) 00278 return _wait_console_active(); 00279 } 00280 00281 bool SPWFSAxx::reset(void) 00282 { 00283 bool ret; 00284 00285 /* save current setting in flash */ 00286 if(!(_parser.send(SPWFXX_SEND_SAVE_SETTINGS) && _recv_ok())) 00287 { 00288 debug_if(_dbg_on, "\r\nSPWF> error saving configuration to flash (%s, %d)\r\n", __func__, __LINE__); 00289 return false; 00290 } 00291 00292 if(!_parser.send(SPWFXX_SEND_SW_RESET)) return false; /* betzw - NOTE: "keep the current state and reset the device". 00293 We assume that the module informs us about the 00294 eventual closing of sockets via "WIND" asynchronous 00295 indications! So everything regarding the clean-up 00296 of these situations is handled there. */ 00297 00298 /* waiting for HW to start */ 00299 ret = _wait_wifi_hw_started(); 00300 00301 return ret; 00302 } 00303 00304 /* Security Mode 00305 None = 0, 00306 WEP = 1, 00307 WPA_Personal = 2, 00308 */ 00309 bool SPWFSAxx::connect(const char *ap, const char *passPhrase, int securityMode) 00310 { 00311 int trials; 00312 00313 BlockExecuter netsock_wa_obj(Callback<void()>(this, &SPWFSAxx::_unblock_event_callback), 00314 Callback<void()>(this, &SPWFSAxx::_block_event_callback)); /* disable calling (external) callback in IRQ context */ 00315 00316 //AT+S.SCFG=wifi_wpa_psk_text,%s 00317 if(!(_parser.send("AT+S.SCFG=wifi_wpa_psk_text,%s", passPhrase) && _recv_ok())) 00318 { 00319 debug_if(_dbg_on, "\r\nSPWF> error pass set\r\n"); 00320 return false; 00321 } 00322 00323 //AT+S.SSIDTXT=%s 00324 if(!(_parser.send("AT+S.SSIDTXT=%s", ap) && _recv_ok())) 00325 { 00326 debug_if(_dbg_on, "\r\nSPWF> error ssid set\r\n"); 00327 return false; 00328 } 00329 00330 //AT+S.SCFG=wifi_priv_mode,%d 00331 if(!(_parser.send("AT+S.SCFG=wifi_priv_mode,%d", securityMode) && _recv_ok())) 00332 { 00333 debug_if(_dbg_on, "\r\nSPWF> error security mode set\r\n"); 00334 return false; 00335 } 00336 00337 /*set STA mode (0->idle, 1->STA,3->miniAP, 2->IBSS)*/ 00338 if(!(_parser.send("AT+S.SCFG=wifi_mode,1") && _recv_ok())) 00339 { 00340 debug_if(_dbg_on, "\r\nSPWF> error WiFi mode set 1 (STA)\r\n"); 00341 return false; 00342 } 00343 00344 /* sw reset */ 00345 if(!reset()) { 00346 debug_if(_dbg_on, "\r\nSPWF> SW reset failed (%s, %d)\r\n", __func__, __LINE__); 00347 return false; 00348 } 00349 00350 trials = 0; 00351 while(true) { 00352 if(_parser.recv("%255[^\n]\n", _msg_buffer) && _recv_delim_lf()) 00353 { 00354 if(strstr(_msg_buffer, ":24:") != NULL) { // WiFi Up 00355 debug_if(_dbg_on, "AT^ %s\n", _msg_buffer); 00356 if(strchr(_msg_buffer, '.') != NULL) { // IPv4 address 00357 break; 00358 } else { 00359 continue; 00360 } 00361 } 00362 if(strstr(_msg_buffer, ":40:") != NULL) { // Deauthentication 00363 debug_if(_dbg_on, "AT~ %s\n", _msg_buffer); 00364 if(++trials < SPWFXX_MAX_TRIALS) { // give it three trials 00365 continue; 00366 } 00367 disconnect(); 00368 empty_rx_buffer(); 00369 return false; 00370 } else { 00371 debug_if(_dbg_on, "AT] %s\n", _msg_buffer); 00372 } 00373 continue; 00374 } 00375 if(++trials >= SPWFXX_MAX_TRIALS) { 00376 debug("\r\nSPWF> ERROR: Should never happen! (%s, %d)\r\n", __func__, __LINE__); 00377 empty_rx_buffer(); 00378 return false; 00379 } 00380 } 00381 00382 return true; 00383 } 00384 00385 bool SPWFSAxx::disconnect(void) 00386 { 00387 BlockExecuter netsock_wa_obj(Callback<void()>(this, &SPWFSAxx::_unblock_event_callback), 00388 Callback<void()>(this, &SPWFSAxx::_block_event_callback)); /* disable calling (external) callback in IRQ context */ 00389 00390 #if MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1 00391 /*disable Wi-Fi device*/ 00392 if(!(_parser.send("AT+S.WIFI=0") && _recv_ok())) 00393 { 00394 debug_if(_dbg_on, "\r\nSPWF> error disabling WiFi\r\n"); 00395 return false; 00396 } 00397 #endif // IDW04A1 00398 00399 /*set idle mode (0->idle, 1->STA,3->miniAP, 2->IBSS)*/ 00400 if(!(_parser.send("AT+S.SCFG=wifi_mode,0") && _recv_ok())) 00401 { 00402 debug_if(_dbg_on, "\r\nSPWF> error WiFi mode set idle (%d)\r\n", __LINE__); 00403 return false; 00404 } 00405 00406 #if MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1 00407 /*enable Wi-Fi device*/ 00408 if(!(_parser.send("AT+S.WIFI=1") && _recv_ok())) 00409 { 00410 debug_if(_dbg_on, "\r\nSPWF> error enabling WiFi\r\n"); 00411 return false; 00412 } 00413 #endif // IDW04A1 00414 00415 // reset module 00416 if(!reset()) { 00417 debug_if(_dbg_on, "\r\nSPWF> SW reset failed (%s, %d)\r\n", __func__, __LINE__); 00418 return false; 00419 } 00420 00421 /* clean up state */ 00422 _associated_interface.inner_constructor(); 00423 _free_all_packets(); 00424 00425 return true; 00426 } 00427 00428 const char *SPWFSAxx::getIPAddress(void) 00429 { 00430 unsigned int n1, n2, n3, n4; 00431 00432 BlockExecuter netsock_wa_obj(Callback<void()>(this, &SPWFSAxx::_unblock_event_callback), 00433 Callback<void()>(this, &SPWFSAxx::_block_event_callback)); /* disable calling (external) callback in IRQ context */ 00434 00435 if (!(_parser.send("AT+S.STS=ip_ipaddr") 00436 && _parser.recv(SPWFXX_RECV_IP_ADDR, &n1, &n2, &n3, &n4) 00437 && _recv_ok())) { 00438 debug_if(_dbg_on, "\r\nSPWF> get IP address error\r\n"); 00439 return NULL; 00440 } 00441 00442 debug_if(_dbg_on, "AT^ ip_ipaddr = %u.%u.%u.%u\r\n", n1, n2, n3, n4); 00443 00444 sprintf((char*)_ip_buffer,"%u.%u.%u.%u", n1, n2, n3, n4); 00445 return _ip_buffer; 00446 } 00447 00448 const char *SPWFSAxx::getGateway(void) 00449 { 00450 unsigned int n1, n2, n3, n4; 00451 00452 BlockExecuter netsock_wa_obj(Callback<void()>(this, &SPWFSAxx::_unblock_event_callback), 00453 Callback<void()>(this, &SPWFSAxx::_block_event_callback)); /* disable calling (external) callback in IRQ context */ 00454 00455 if (!(_parser.send("AT+S.STS=ip_gw") 00456 && _parser.recv(SPWFXX_RECV_GATEWAY, &n1, &n2, &n3, &n4) 00457 && _recv_ok())) { 00458 debug_if(_dbg_on, "\r\nSPWF> get gateway error\r\n"); 00459 return NULL; 00460 } 00461 00462 debug_if(_dbg_on, "AT^ ip_gw = %u.%u.%u.%u\r\n", n1, n2, n3, n4); 00463 00464 sprintf((char*)_gateway_buffer,"%u.%u.%u.%u", n1, n2, n3, n4); 00465 return _gateway_buffer; 00466 } 00467 00468 const char *SPWFSAxx::getNetmask(void) 00469 { 00470 unsigned int n1, n2, n3, n4; 00471 00472 BlockExecuter netsock_wa_obj(Callback<void()>(this, &SPWFSAxx::_unblock_event_callback), 00473 Callback<void()>(this, &SPWFSAxx::_block_event_callback)); /* disable calling (external) callback in IRQ context */ 00474 00475 if (!(_parser.send("AT+S.STS=ip_netmask") 00476 && _parser.recv(SPWFXX_RECV_NETMASK, &n1, &n2, &n3, &n4) 00477 && _recv_ok())) { 00478 debug_if(_dbg_on, "\r\nSPWF> get netmask error\r\n"); 00479 return NULL; 00480 } 00481 00482 debug_if(_dbg_on, "AT^ ip_netmask = %u.%u.%u.%u\r\n", n1, n2, n3, n4); 00483 00484 sprintf((char*)_netmask_buffer,"%u.%u.%u.%u", n1, n2, n3, n4); 00485 return _netmask_buffer; 00486 } 00487 00488 int8_t SPWFSAxx::getRssi(void) 00489 { 00490 int ret; 00491 00492 BlockExecuter netsock_wa_obj(Callback<void()>(this, &SPWFSAxx::_unblock_event_callback), 00493 Callback<void()>(this, &SPWFSAxx::_block_event_callback)); /* disable calling (external) callback in IRQ context */ 00494 00495 if (!(_parser.send("AT+S.PEERS=0,rx_rssi") 00496 && _parser.recv(SPWFXX_RECV_RX_RSSI, &ret) 00497 && _recv_ok())) { 00498 debug_if(_dbg_on, "\r\nSPWF> get RX rssi error\r\n"); 00499 return 0; 00500 } 00501 00502 return (int8_t)ret; 00503 } 00504 00505 const char *SPWFSAxx::getMACAddress(void) 00506 { 00507 unsigned int n1, n2, n3, n4, n5, n6; 00508 00509 BlockExecuter netsock_wa_obj(Callback<void()>(this, &SPWFSAxx::_unblock_event_callback), 00510 Callback<void()>(this, &SPWFSAxx::_block_event_callback)); /* disable calling (external) callback in IRQ context */ 00511 00512 if (!(_parser.send("AT+S.GCFG=nv_wifi_macaddr") 00513 && _parser.recv(SPWFXX_RECV_MAC_ADDR, &n1, &n2, &n3, &n4, &n5, &n6) 00514 && _recv_ok())) { 00515 debug_if(_dbg_on, "\r\nSPWF> get MAC address error\r\n"); 00516 return 0; 00517 } 00518 00519 debug_if(_dbg_on, "AT^ nv_wifi_macaddr = %x:%x:%x:%x:%x:%x\r\n", n1, n2, n3, n4, n5, n6); 00520 00521 sprintf((char*)_mac_buffer,"%02X:%02X:%02X:%02X:%02X:%02X", n1, n2, n3, n4, n5, n6); 00522 return _mac_buffer; 00523 } 00524 00525 bool SPWFSAxx::isConnected(void) 00526 { 00527 return _associated_interface._connected_to_network; 00528 } 00529 00530 nsapi_size_or_error_t SPWFSAxx::send(int spwf_id, const void *data, uint32_t amount, int internal_id) 00531 { 00532 uint32_t sent = 0U, to_send; 00533 nsapi_size_or_error_t ret; 00534 00535 BlockExecuter netsock_wa_obj(Callback<void()>(this, &SPWFSAxx::_unblock_event_callback), 00536 Callback<void()>(this, &SPWFSAxx::_block_event_callback)); /* disable calling (external) callback in IRQ context */ 00537 00538 _process_winds(); // perform async indication handling (to early detect eventually closed sockets) 00539 00540 /* betzw - WORK AROUND module FW issues: split up big packages in smaller ones */ 00541 for(to_send = (amount > SPWFXX_SEND_RECV_PKTSIZE) ? SPWFXX_SEND_RECV_PKTSIZE : amount; 00542 sent < amount; 00543 to_send = ((amount - sent) > SPWFXX_SEND_RECV_PKTSIZE) ? SPWFXX_SEND_RECV_PKTSIZE : (amount - sent)) { 00544 { 00545 BlockExecuter bh_handler(Callback<void()>(this, &SPWFSAxx::_execute_bottom_halves)); 00546 00547 // betzw - TODO: handle different errors more accurately! 00548 if (!_associated_interface._socket_is_still_connected(internal_id)) { 00549 debug_if(_dbg_on, "\r\nSPWF> Socket not connected anymore: sent=%u, to_send=%u! (%s, %d)\r\n", sent, to_send, __func__, __LINE__); 00550 break; 00551 } else if(!_parser.send("AT+S.SOCKW=%d,%d", spwf_id, (unsigned int)to_send)) { 00552 debug_if(_dbg_on, "\r\nSPWF> Sending command failed: sent=%u, to_send=%u! (%s, %d)\r\n", sent, to_send, __func__, __LINE__); 00553 break; 00554 } else if(_parser.write(((char*)data)+sent, (int)to_send) != (int)to_send) { 00555 debug_if(_dbg_on, "\r\nSPWF> Sending data failed: sent=%u, to_send=%u! (%s, %d)\r\n", sent, to_send, __func__, __LINE__); 00556 break; 00557 } else if(!_recv_ok()) { 00558 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__); 00559 break; 00560 } 00561 } 00562 00563 sent += to_send; 00564 } 00565 00566 if(sent > 0) { // `sent == 0` indicates a potential error 00567 ret = sent; 00568 } else if(amount == 0) { 00569 ret = NSAPI_ERROR_OK; 00570 } else if(_associated_interface._socket_is_still_connected(internal_id)) { 00571 ret = NSAPI_ERROR_DEVICE_ERROR; 00572 } else { 00573 ret = NSAPI_ERROR_CONNECTION_LOST; 00574 } 00575 00576 return ret; 00577 } 00578 00579 int SPWFSAxx::_read_len(int spwf_id) { 00580 unsigned int amount; 00581 00582 if (!(_parser.send("AT+S.SOCKQ=%d", spwf_id) 00583 && _parser.recv(SPWFXX_RECV_DATALEN, &amount) 00584 && _recv_ok())) { 00585 debug_if(_dbg_on, "\r\nSPWF> %s failed\r\n", __func__); 00586 return SPWFXX_ERR_LEN; 00587 } 00588 00589 if(amount > 0) { 00590 debug_if(_dbg_on, "\r\nSPWF> %s():\t\t%d:%d\r\n", __func__, spwf_id, amount); 00591 } 00592 00593 MBED_ASSERT(((int)amount) >= 0); 00594 00595 return (int)amount; 00596 } 00597 00598 #define SPWFXX_WINDS_OFF "0xFFFFFFFF" 00599 00600 void SPWFSAxx::_winds_on(void) { 00601 MBED_ASSERT(_is_event_callback_blocked()); 00602 00603 if(!(_parser.send(SPWFXX_SEND_WIND_OFF_HIGH SPWFXX_WINDS_HIGH_ON) && _recv_ok())) { 00604 debug_if(_dbg_on, "\r\nSPWF> %s failed at line #%d\r\n", __func__, __LINE__); 00605 } 00606 if(!(_parser.send(SPWFXX_SEND_WIND_OFF_MEDIUM SPWFXX_WINDS_MEDIUM_ON) && _recv_ok())) { 00607 debug_if(_dbg_on, "\r\nSPWF> %s failed at line #%d\r\n", __func__, __LINE__); 00608 } 00609 if(!(_parser.send(SPWFXX_SEND_WIND_OFF_LOW SPWFXX_WINDS_LOW_ON) && _recv_ok())) { 00610 debug_if(_dbg_on, "\r\nSPWF> %s failed at line #%d\r\n", __func__, __LINE__); 00611 } 00612 } 00613 00614 /* Define beyond macro in case you want to report back failures in switching off WINDs to the caller */ 00615 // #define SPWFXX_SOWF 00616 /* Note: in case of error blocking has been (tried to be) lifted */ 00617 bool SPWFSAxx::_winds_off(void) { 00618 MBED_ASSERT(_is_event_callback_blocked()); 00619 00620 if (!(_parser.send(SPWFXX_SEND_WIND_OFF_LOW SPWFXX_WINDS_OFF) 00621 && _recv_ok())) { 00622 debug_if(_dbg_on, "\r\nSPWF> %s failed at line #%d\r\n", __func__, __LINE__); 00623 #ifdef SPWFXX_SOWF // betzw: try to continue 00624 _winds_on(); 00625 return false; 00626 #endif 00627 } 00628 00629 if (!(_parser.send(SPWFXX_SEND_WIND_OFF_MEDIUM SPWFXX_WINDS_OFF) 00630 && _recv_ok())) { 00631 debug_if(_dbg_on, "\r\nSPWF> %s failed at line #%d\r\n", __func__, __LINE__); 00632 #ifdef SPWFXX_SOWF // betzw: try to continue 00633 _winds_on(); 00634 return false; 00635 #endif 00636 } 00637 00638 if (!(_parser.send(SPWFXX_SEND_WIND_OFF_HIGH SPWFXX_WINDS_OFF) 00639 && _recv_ok())) { 00640 debug_if(_dbg_on, "\r\nSPWF> %s failed at line #%d\r\n", __func__, __LINE__); 00641 #ifdef SPWFXX_SOWF // betzw: try to continue 00642 _winds_on(); 00643 return false; 00644 #endif 00645 } 00646 00647 return true; 00648 } 00649 00650 void SPWFSAxx::_execute_bottom_halves(void) { 00651 _network_lost_handler_bh(); 00652 _packet_handler_bh(); 00653 } 00654 00655 void SPWFSAxx::_read_in_pending(void) { 00656 static int internal_id_cnt = 0; 00657 00658 while(_is_data_pending()) { 00659 if(_associated_interface._socket_has_connected(internal_id_cnt)) { 00660 int spwf_id = _associated_interface._ids[internal_id_cnt].spwf_id; 00661 00662 if(_is_data_pending(spwf_id)) { 00663 int amount; 00664 00665 amount = _read_in_pkt(spwf_id, false); 00666 if(amount == SPWFXX_ERR_OOM) { /* consider only 'SPWFXX_ERR_OOM' as non recoverable */ 00667 return; 00668 } 00669 } 00670 00671 if(!_is_data_pending(spwf_id)) { 00672 internal_id_cnt++; 00673 internal_id_cnt %= SPWFSA_SOCKET_COUNT; 00674 } 00675 } else { 00676 internal_id_cnt++; 00677 internal_id_cnt %= SPWFSA_SOCKET_COUNT; 00678 } 00679 } 00680 } 00681 00682 /* Note: returns 00683 * 'SPWFXX_ERR_OK' in case of success 00684 * 'SPWFXX_ERR_OOM' in case of "out of memory" 00685 * 'SPWFXX_ERR_READ' in case of `_read_in()` error 00686 */ 00687 int SPWFSAxx::_read_in_packet(int spwf_id, uint32_t amount) { 00688 struct packet *packet = (struct packet*)malloc(sizeof(struct packet) + amount); 00689 if (!packet) { 00690 #ifndef NDEBUG 00691 error("\r\nSPWF> %s(%d): Out of memory!\r\n", __func__, __LINE__); 00692 #else // NDEBUG 00693 debug("\r\nSPWF> %s(%d): Out of memory!\r\n", __func__, __LINE__); 00694 #endif 00695 debug_if(_dbg_on, "\r\nSPWF> %s failed (%d)\r\n", __func__, __LINE__); 00696 return SPWFXX_ERR_OOM; /* out of memory: give up here! */ 00697 } 00698 00699 /* init packet */ 00700 packet->id = spwf_id; 00701 packet->len = amount; 00702 packet->next = 0; 00703 00704 /* read data in */ 00705 if(!(_read_in((char*)(packet + 1), spwf_id, amount) > 0)) { 00706 free(packet); 00707 debug_if(_dbg_on, "\r\nSPWF> %s failed (%d)\r\n", __func__, __LINE__); 00708 return SPWFXX_ERR_READ; 00709 } else { 00710 debug_if(_dbg_on, "\r\nSPWF> %s():\t%d:%d\r\n", __func__, spwf_id, amount); 00711 00712 /* append to packet list */ 00713 *_packets_end = packet; 00714 _packets_end = &packet->next; 00715 00716 /* force call of (external) callback */ 00717 _call_callback(); 00718 } 00719 00720 return SPWFXX_ERR_OK; 00721 } 00722 00723 void SPWFSAxx::_free_packets(int spwf_id) { 00724 // check if any packets are ready for `spwf_id` 00725 for(struct packet **p = &_packets; *p;) { 00726 if ((*p)->id == spwf_id) { 00727 struct packet *q = *p; 00728 if (_packets_end == &(*p)->next) { 00729 _packets_end = p; 00730 } 00731 *p = (*p)->next; 00732 free(q); 00733 } else { 00734 p = &(*p)->next; 00735 } 00736 } 00737 } 00738 00739 void SPWFSAxx::_free_all_packets() { 00740 for (int spwf_id = 0; spwf_id < SPWFSA_SOCKET_COUNT; spwf_id++) { 00741 _free_packets(spwf_id); 00742 } 00743 } 00744 00745 bool SPWFSAxx::close(int spwf_id) 00746 { 00747 bool ret = false; 00748 00749 BlockExecuter netsock_wa_obj(Callback<void()>(this, &SPWFSAxx::_unblock_event_callback), 00750 Callback<void()>(this, &SPWFSAxx::_block_event_callback)); /* disable calling (external) callback in IRQ context */ 00751 00752 MBED_ASSERT(((unsigned int)spwf_id) < ((unsigned int)SPWFSA_SOCKET_COUNT)); // `spwf_id` is valid 00753 00754 for(int retry_cnt = 0; retry_cnt < SPWFXX_MAX_TRIALS; retry_cnt++) { 00755 Timer timer; 00756 timer.start(); 00757 00758 // Flush out pending data 00759 while(true) { 00760 int amount = _read_in_pkt(spwf_id, true); 00761 if(amount < 0) { // SPWFXX error 00762 /* empty RX buffer & try to close */ 00763 empty_rx_buffer(); 00764 break; 00765 } 00766 if(amount == 0) break; // no more data to be read 00767 00768 /* Try to work around module API bug: 00769 * break out & try to close after 20 seconds 00770 */ 00771 if(timer.read() > 20) { 00772 break; 00773 } 00774 00775 /* immediately free packet(s) (to avoid "out of memory") */ 00776 _free_packets(spwf_id); 00777 00778 /* interleave bottom halves */ 00779 _execute_bottom_halves(); 00780 } 00781 00782 // Close socket 00783 if (_parser.send("AT+S.SOCKC=%d", spwf_id) 00784 && _recv_ok()) { 00785 ret = true; 00786 break; // finish closing 00787 } else { // close failed 00788 debug_if(_dbg_on, "\r\nSPWF> %s failed (%d)\r\n", __func__, __LINE__); 00789 /* interleave bottom halves */ 00790 _execute_bottom_halves(); 00791 00792 /* free packets */ 00793 _free_packets(spwf_id); 00794 } 00795 } 00796 00797 /* anticipate bottom halves */ 00798 _execute_bottom_halves(); 00799 00800 if(ret) { 00801 /* clear pending data flag (should be redundant) */ 00802 _clear_pending_data(spwf_id); 00803 00804 /* free packets for this socket */ 00805 _free_packets(spwf_id); 00806 00807 /* reset pending data sizes */ 00808 _reset_pending_pkt_sizes(spwf_id); 00809 } else { 00810 debug_if(_dbg_on, "\r\nSPWF> SPWFSAxx::close failed (%d)\r\n", __LINE__); 00811 00812 int internal_id = _associated_interface.get_internal_id(spwf_id); 00813 if(!_associated_interface._socket_is_still_connected(internal_id)) { 00814 /* clear pending data flag (should be redundant) */ 00815 _clear_pending_data(spwf_id); 00816 00817 /* free packets for this socket */ 00818 _free_packets(spwf_id); 00819 00820 /* reset pending data sizes */ 00821 _reset_pending_pkt_sizes(spwf_id); 00822 00823 ret = true; 00824 } 00825 } 00826 00827 return ret; 00828 } 00829 00830 /* 00831 * Buffered serial event handler 00832 * 00833 * Note: executed in IRQ context! 00834 * Note: do not call (external) callback in IRQ context while performing critical module operations 00835 */ 00836 void SPWFSAxx::_event_handler(void) 00837 { 00838 if(!_is_event_callback_blocked()) { 00839 _call_callback(); 00840 } 00841 } 00842 00843 /* 00844 * Common error handler 00845 */ 00846 void SPWFSAxx::_error_handler(void) 00847 { 00848 if(_parser.recv("%255[^\n]\n", _msg_buffer) && _recv_delim_lf()) { 00849 debug_if(_dbg_on, "AT^ ERROR:%s (%d)\r\n", _msg_buffer, __LINE__); 00850 } else { 00851 debug_if(_dbg_on, "\r\nSPWF> Unknown ERROR string in SPWFSAxx::_error_handler (%d)\r\n", __LINE__); 00852 } 00853 00854 /* force call of (external) callback */ 00855 _call_callback(); 00856 } 00857 00858 /* 00859 * Handling oob ("+WIND:33:WiFi Network Lost") 00860 */ 00861 void SPWFSAxx::_network_lost_handler_th(void) 00862 { 00863 #ifndef NDEBUG 00864 static unsigned int net_loss_cnt = 0; 00865 net_loss_cnt++; 00866 #endif 00867 00868 _recv_delim_cr_lf(); 00869 00870 debug_if(_dbg_on, "AT^ +WIND:33:WiFi Network Lost\r\n"); 00871 00872 #ifndef NDEBUG 00873 debug_if(_dbg_on, "\r\nSPWF> Getting out of SPWFSAxx::_network_lost_handler_th: %d\r\n", net_loss_cnt); 00874 #else // NDEBUG 00875 debug_if(_dbg_on, "\r\nSPWF> Getting out of SPWFSAxx::_network_lost_handler_th: %d\r\n", __LINE__); 00876 #endif // NDEBUG 00877 00878 /* set flag to signal network loss */ 00879 _network_lost_flag = true; 00880 00881 /* force call of (external) callback */ 00882 _call_callback(); 00883 00884 return; 00885 } 00886 00887 /* betzw - WORK AROUND module FW issues: split up big packages in smaller ones */ 00888 void SPWFSAxx::_add_pending_packet_sz(int spwf_id, uint32_t size) { 00889 uint32_t to_add; 00890 uint32_t added = _get_cumulative_size(spwf_id); 00891 00892 if(size <= added) { // might happen due to delayed WIND delivery 00893 debug_if(_dbg_on, "\r\nSPWF> WARNING: %s failed at line #%d\r\n", __func__, __LINE__); 00894 return; 00895 } 00896 00897 for(to_add = ((size - added) > SPWFXX_SEND_RECV_PKTSIZE) ? SPWFXX_SEND_RECV_PKTSIZE : (size - added); 00898 added < size; 00899 to_add = ((size - added) > SPWFXX_SEND_RECV_PKTSIZE) ? SPWFXX_SEND_RECV_PKTSIZE : (size - added)) { 00900 _add_pending_pkt_size(spwf_id, added + to_add); 00901 added += to_add; 00902 } 00903 00904 /* force call of (external) callback */ 00905 _call_callback(); 00906 00907 /* set that data is pending */ 00908 _set_pending_data(spwf_id); 00909 } 00910 00911 /* 00912 * Handling oob ("+WIND:55:Pending Data") 00913 */ 00914 void SPWFSAxx::_packet_handler_th(void) 00915 { 00916 int internal_id, spwf_id; 00917 int amount; 00918 00919 /* parse out the socket id & amount */ 00920 if (!(_parser.recv(SPWFXX_RECV_PENDING_DATA, &spwf_id, &amount) && _recv_delim_lf())) { 00921 #ifndef NDEBUG 00922 error("\r\nSPWF> SPWFSAxx::%s failed!\r\n", __func__); 00923 #endif 00924 return; 00925 } 00926 00927 debug_if(_dbg_on, "AT^ +WIND:55:Pending Data:%d:%d\r\n", spwf_id, amount); 00928 00929 /* check for the module to report a valid id */ 00930 MBED_ASSERT(((unsigned int)spwf_id) < ((unsigned int)SPWFSA_SOCKET_COUNT)); 00931 00932 /* set that there is pending data for socket */ 00933 /* NOTE: it seems as if asynchronous indications might report not up-to-date data length values 00934 * therefore we just record the socket id without considering the `amount` of data reported! 00935 */ 00936 internal_id = _associated_interface.get_internal_id(spwf_id); 00937 if(internal_id != SPWFSA_SOCKET_COUNT) { 00938 debug_if(_dbg_on, "AT^ +WIND:55:Pending Data:%d:%d - #2\r\n", spwf_id, amount); 00939 _add_pending_packet_sz(spwf_id, amount); 00940 00941 MBED_ASSERT(_get_pending_pkt_size(spwf_id) != 0); 00942 } else { 00943 debug_if(_dbg_on, "\r\nSPWFSAxx::%s got invalid id %d\r\n", __func__, spwf_id); 00944 } 00945 } 00946 00947 void SPWFSAxx::_network_lost_handler_bh(void) 00948 { 00949 if(!_network_lost_flag) return; 00950 _network_lost_flag = false; 00951 00952 { 00953 bool were_connected; 00954 BlockExecuter netsock_wa_obj(Callback<void()>(this, &SPWFSAxx::_unblock_event_callback), 00955 Callback<void()>(this, &SPWFSAxx::_block_event_callback)); /* do not call (external) callback in IRQ context as long as network is lost */ 00956 Timer timer; 00957 timer.start(); 00958 00959 _parser.set_timeout(SPWF_NETLOST_TIMEOUT); 00960 00961 were_connected = isConnected(); 00962 _associated_interface._connected_to_network = false; 00963 00964 if(were_connected) { 00965 unsigned int n1, n2, n3, n4; 00966 00967 while(true) { 00968 if (timer.read_ms() > SPWF_CONNECT_TIMEOUT) { 00969 debug_if(_dbg_on, "\r\nSPWF> SPWFSAxx::_network_lost_handler_bh() #%d\r\n", __LINE__); 00970 disconnect(); 00971 empty_rx_buffer(); 00972 goto nlh_get_out; 00973 } 00974 00975 if((_parser.recv(SPWFXX_RECV_WIFI_UP, &n1, &n2, &n3, &n4)) && _recv_delim_lf()) { 00976 debug_if(_dbg_on, "\r\nSPWF> Re-connected (%u.%u.%u.%u)!\r\n", n1, n2, n3, n4); 00977 00978 _associated_interface._connected_to_network = true; 00979 goto nlh_get_out; 00980 } 00981 } 00982 } else { 00983 debug_if(_dbg_on, "\r\nSPWF> Leaving SPWFSAxx::_network_lost_handler_bh\r\n"); 00984 goto nlh_get_out; 00985 } 00986 00987 nlh_get_out: 00988 debug_if(_dbg_on, "\r\nSPWF> Getting out of SPWFSAxx::_network_lost_handler_bh\r\n"); 00989 _parser.set_timeout(_timeout); 00990 00991 /* force call of (external) callback */ 00992 _call_callback(); 00993 00994 return; 00995 } 00996 } 00997 00998 void SPWFSAxx::_recover_from_hard_faults(void) { 00999 disconnect(); 01000 empty_rx_buffer(); 01001 01002 /* force call of (external) callback */ 01003 _call_callback(); 01004 } 01005 01006 /* 01007 * Handling oob ("+WIND:8:Hard Fault") 01008 */ 01009 void SPWFSAxx::_hard_fault_handler(void) 01010 { 01011 _parser.set_timeout(SPWF_RECV_TIMEOUT); 01012 if(_parser.recv("%255[^\n]\n", _msg_buffer) && _recv_delim_lf()) { 01013 #ifndef NDEBUG 01014 error("\r\nSPWF> hard fault error:\r\n%s\r\n", _msg_buffer); 01015 #else // NDEBUG 01016 debug("\r\nSPWF> hard fault error:\r\n%s\r\n", _msg_buffer); 01017 #endif // NDEBUG 01018 } else { 01019 #ifndef NDEBUG 01020 error("\r\nSPWF> unknown hard fault error\r\n"); 01021 #else // NDEBUG 01022 debug("\r\nSPWF> unknown hard fault error\r\n"); 01023 #endif // NDEBUG 01024 } 01025 01026 // This is most likely the best we can do to recover from this module hard fault 01027 _parser.set_timeout(SPWF_HF_TIMEOUT); 01028 _recover_from_hard_faults(); 01029 _parser.set_timeout(_timeout); 01030 01031 /* force call of (external) callback */ 01032 _call_callback(); 01033 } 01034 01035 /* 01036 * Handling oob ("+WIND:5:WiFi Hardware Failure") 01037 */ 01038 void SPWFSAxx::_wifi_hwfault_handler(void) 01039 { 01040 unsigned int failure_nr; 01041 01042 /* parse out the socket id & amount */ 01043 _parser.recv(":%u\n", &failure_nr); 01044 _recv_delim_lf(); 01045 01046 #ifndef NDEBUG 01047 error("\r\nSPWF> WiFi HW fault error: %u\r\n", failure_nr); 01048 #else // NDEBUG 01049 debug("\r\nSPWF> WiFi HW fault error: %u\r\n", failure_nr); 01050 01051 // This is most likely the best we can do to recover from this module hard fault 01052 _parser.set_timeout(SPWF_HF_TIMEOUT); 01053 _recover_from_hard_faults(); 01054 _parser.set_timeout(_timeout); 01055 #endif // NDEBUG 01056 01057 /* force call of (external) callback */ 01058 _call_callback(); 01059 } 01060 01061 /* 01062 * Handling oob ("+WIND:58:Socket Closed") 01063 * when server closes a client connection 01064 * 01065 * NOTE: When a socket client receives an indication about socket server gone (only for TCP sockets, WIND:58), 01066 * the socket connection is NOT automatically closed! 01067 */ 01068 void SPWFSAxx::_server_gone_handler(void) 01069 { 01070 int spwf_id, internal_id; 01071 01072 if(!(_parser.recv(SPWFXX_RECV_SOCKET_CLOSED, &spwf_id) && _recv_delim_lf())) { 01073 #ifndef NDEBUG 01074 error("\r\nSPWF> SPWFSAxx::%s failed!\r\n", __func__); 01075 #endif 01076 goto _get_out; 01077 } 01078 01079 debug_if(_dbg_on, "AT^ +WIND:58:Socket Closed:%d\r\n", spwf_id); 01080 01081 /* check for the module to report a valid id */ 01082 MBED_ASSERT(((unsigned int)spwf_id) < ((unsigned int)SPWFSA_SOCKET_COUNT)); 01083 01084 /* only set `server_gone` 01085 * user still can receive data & must still explicitly close the socket 01086 */ 01087 internal_id = _associated_interface.get_internal_id(spwf_id); 01088 if(internal_id != SPWFSA_SOCKET_COUNT) { 01089 _associated_interface._ids[internal_id].server_gone = true; 01090 } 01091 01092 _get_out: 01093 /* force call of (external) callback */ 01094 _call_callback(); 01095 } 01096 01097 #if MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1 01098 /* 01099 * Handling oob (currently only for "+WIND:24:WiFi Up::") 01100 */ 01101 void SPWFSAxx::_skip_oob(void) 01102 { 01103 if(_parser.recv("%255[^\n]\n", _msg_buffer) && _recv_delim_lf()) { 01104 debug_if(_dbg_on, "AT^ +WIND:24:WiFi Up::%s\r\n", _msg_buffer); 01105 } else { 01106 debug_if(_dbg_on, "\r\nSPWF> Invalid string in SPWFSAxx::_skip_oob (%d)\r\n", __LINE__); 01107 } 01108 } 01109 #endif 01110 01111 void SPWFSAxx::setTimeout(uint32_t timeout_ms) 01112 { 01113 _timeout = timeout_ms; 01114 _parser.set_timeout(timeout_ms); 01115 } 01116 01117 void SPWFSAxx::attach(Callback<void()> func) 01118 { 01119 _callback_func = func; /* do not call (external) callback in IRQ context during critical module operations */ 01120 } 01121 01122 /** 01123 * Recv Function 01124 */ 01125 int32_t SPWFSAxx::recv(int spwf_id, void *data, uint32_t amount, bool datagram) 01126 { 01127 BlockExecuter bh_handler(Callback<void()>(this, &SPWFSAxx::_execute_bottom_halves)); 01128 01129 while (true) { 01130 /* check if any packets are ready for us */ 01131 for (struct packet **p = &_packets; *p; p = &(*p)->next) { 01132 if ((*p)->id == spwf_id) { 01133 debug_if(_dbg_on, "\r\nSPWF> Read done on ID %d and length of packet is %d\r\n",spwf_id,(*p)->len); 01134 struct packet *q = *p; 01135 01136 MBED_ASSERT(q->len > 0); 01137 01138 if(datagram) { // UDP => always remove pkt size 01139 // will always consume a whole pending size 01140 uint32_t ret; 01141 01142 debug_if(_dbg_on, "\r\nSPWF> %s():\t\t\t%d:%d (datagram)\r\n", __func__, spwf_id, q->len); 01143 01144 ret = (amount < q->len) ? amount : q->len; 01145 memcpy(data, q+1, ret); 01146 01147 if (_packets_end == &(*p)->next) { 01148 _packets_end = p; 01149 } 01150 *p = (*p)->next; 01151 free(q); 01152 01153 return ret; 01154 } else { // TCP 01155 if (q->len <= amount) { // return and remove full packet 01156 memcpy(data, q+1, q->len); 01157 01158 if (_packets_end == &(*p)->next) { 01159 _packets_end = p; 01160 } 01161 *p = (*p)->next; 01162 uint32_t len = q->len; 01163 free(q); 01164 01165 return len; 01166 } else { // `q->len > amount`, return only partial packet 01167 if(amount > 0) { 01168 memcpy(data, q+1, amount); 01169 q->len -= amount; 01170 memmove(q+1, (uint8_t*)(q+1) + amount, q->len); 01171 } 01172 01173 return amount; 01174 } 01175 } 01176 } 01177 } 01178 01179 /* check for pending data on module */ 01180 { 01181 int len; 01182 01183 len = _read_in_pkt(spwf_id, false); 01184 if(len <= 0) { /* SPWFXX error or no more data to be read */ 01185 return -1; 01186 } 01187 } 01188 } 01189 } 01190 01191 void SPWFSAxx::_process_winds(void) { 01192 do { 01193 if(_parser.process_oob()) { 01194 /* nothing else to do! */; 01195 } else { 01196 debug_if(_dbg_on, "%s():\t\tNo (more) oob's found!\r\n", __func__); 01197 return; // no (more) oob's found 01198 } 01199 } while(true); 01200 } 01201 01202 /* Note: returns 01203 * '>=0' in case of success, amount of read in data (in bytes) 01204 * 'SPWFXX_ERR_OOM' in case of "out of memory" 01205 * 'SPWFXX_ERR_READ' in case of other `_read_in_packet()` error 01206 * 'SPWFXX_ERR_LEN' in case of `_read_len()` error 01207 */ 01208 int SPWFSAxx::_read_in_pkt(int spwf_id, bool close) { 01209 int pending; 01210 uint32_t wind_pending; 01211 BlockExecuter netsock_wa_obj(Callback<void()>(this, &SPWFSAxx::_unblock_event_callback), 01212 Callback<void()>(this, &SPWFSAxx::_block_event_callback)); /* do not call (external) callback in IRQ context while receiving */ 01213 01214 _process_winds(); // perform async indication handling 01215 01216 if(close) { // read in all data 01217 wind_pending = pending = _read_len(spwf_id); // triggers also async indication handling! 01218 01219 if(pending > 0) { 01220 /* reset pending data sizes */ 01221 _reset_pending_pkt_sizes(spwf_id); 01222 /* create new entry for pending size */ 01223 _add_pending_pkt_size(spwf_id, (uint32_t)pending); 01224 #ifndef NDEBUG 01225 wind_pending = _get_pending_pkt_size(spwf_id); 01226 MBED_ASSERT(pending == (int)wind_pending); 01227 #endif 01228 } else if(pending < 0) { 01229 debug_if(_dbg_on, "\r\nSPWF> %s(), #%d:`_read_len()` failed (%d)!\r\n", __func__, __LINE__, pending); 01230 } 01231 } else { // only read in already notified data 01232 pending = wind_pending = _get_pending_pkt_size(spwf_id); 01233 if(pending == 0) { // special handling for no packets pending (to WORK AROUND missing WINDs)! 01234 pending = _read_len(spwf_id); // triggers also async indication handling! 01235 01236 if(pending > 0) { 01237 _process_winds(); // perform async indication handling (again) 01238 wind_pending = _get_pending_pkt_size(spwf_id); 01239 01240 if(wind_pending == 0) { 01241 /* betzw - WORK AROUND module FW issues: create new entry for pending size */ 01242 debug_if(_dbg_on, "%s():\t\tAdd packet w/o WIND (%d)!\r\n", __func__, pending); 01243 _add_pending_packet_sz(spwf_id, (uint32_t)pending); 01244 01245 pending = wind_pending = _get_pending_pkt_size(spwf_id); 01246 MBED_ASSERT(wind_pending > 0); 01247 } 01248 } else if(pending < 0) { 01249 debug_if(_dbg_on, "\r\nSPWF> %s(), #%d:`_read_len()` failed (%d)!\r\n", __func__, __LINE__, pending); 01250 } 01251 } 01252 } 01253 01254 if((pending > 0) && (wind_pending > 0)) { 01255 int ret = _read_in_packet(spwf_id, wind_pending); 01256 if(ret < 0) { /* "out of memory" or `_read_in_packet()` error */ 01257 /* we do not know if data is still pending at this point 01258 but leaving the pending data bit set might lead to an endless loop */ 01259 _clear_pending_data(spwf_id); 01260 /* also reset pending data sizes */ 01261 _reset_pending_pkt_sizes(spwf_id); 01262 01263 return ret; 01264 } 01265 01266 if((_get_cumulative_size(spwf_id) == 0) && (pending <= (int)wind_pending)) { 01267 _clear_pending_data(spwf_id); 01268 } 01269 } else if(pending < 0) { /* 'SPWFXX_ERR_LEN' error */ 01270 MBED_ASSERT(pending == SPWFXX_ERR_LEN); 01271 /* we do not know if data is still pending at this point 01272 but leaving the pending data bit set might lead to an endless loop */ 01273 _clear_pending_data(spwf_id); 01274 /* also reset pending data sizes */ 01275 _reset_pending_pkt_sizes(spwf_id); 01276 01277 return pending; 01278 } else if(pending == 0) { 01279 MBED_ASSERT(wind_pending == 0); 01280 _clear_pending_data(spwf_id); 01281 } else if(wind_pending == 0) { // `pending > 0` 01282 /* betzw: should never happen! */ 01283 MBED_ASSERT(false); 01284 } 01285 01286 return (int)wind_pending; 01287 }
Generated on Tue Jul 12 2022 16:22:12 by 1.7.2