Axel Hwang / Mbed OS ProjetIOT

Files at this revision

API Documentation at this revision

Comitter:
axelhwang
Date:
Wed Oct 28 07:42:46 2020 +0000
Commit message:
Push

Changed in this revision

Jenkinsfile Show annotated file Show diff for this revision Revisions of this file
LICENSE Show annotated file Show diff for this revision Revisions of this file
README.md Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-os.lib Show annotated file Show diff for this revision Revisions of this file
mbed_app.json Show annotated file Show diff for this revision Revisions of this file
mbed_app_idw01m1.json Show annotated file Show diff for this revision Revisions of this file
mbed_app_idw04a1.json Show annotated file Show diff for this revision Revisions of this file
mbed_app_ism43362.json Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362.lib Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/ISM43362/ATParser/ATParser.cpp Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/ISM43362/ATParser/ATParser.h Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/ISM43362/ATParser/BufferedSpi/Buffer/MyBuffer.cpp Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/ISM43362/ATParser/BufferedSpi/Buffer/MyBuffer.h Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/ISM43362/ATParser/BufferedSpi/BufferedPrint.c Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/ISM43362/ATParser/BufferedSpi/BufferedSpi.cpp Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/ISM43362/ATParser/BufferedSpi/BufferedSpi.h Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/ISM43362/ISM43362.cpp Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/ISM43362/ISM43362.h Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/ISM43362Interface.cpp Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/ISM43362Interface.h Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/README.md Show annotated file Show diff for this revision Revisions of this file
wifi-x-nucleo-idw01m1.lib Show annotated file Show diff for this revision Revisions of this file
wifi-x-nucleo-idw01m1/.gitignore Show annotated file Show diff for this revision Revisions of this file
wifi-x-nucleo-idw01m1/BlockExecuter.h Show annotated file Show diff for this revision Revisions of this file
wifi-x-nucleo-idw01m1/README.md Show annotated file Show diff for this revision Revisions of this file
wifi-x-nucleo-idw01m1/SPWFSA01/SPWFSA01.cpp Show annotated file Show diff for this revision Revisions of this file
wifi-x-nucleo-idw01m1/SPWFSA01/SPWFSA01.h Show annotated file Show diff for this revision Revisions of this file
wifi-x-nucleo-idw01m1/SPWFSA01/spwfsa01_at_strings.h Show annotated file Show diff for this revision Revisions of this file
wifi-x-nucleo-idw01m1/SPWFSA04/SPWFSA04.cpp Show annotated file Show diff for this revision Revisions of this file
wifi-x-nucleo-idw01m1/SPWFSA04/SPWFSA04.h Show annotated file Show diff for this revision Revisions of this file
wifi-x-nucleo-idw01m1/SPWFSA04/spwfsa04_at_strings.h Show annotated file Show diff for this revision Revisions of this file
wifi-x-nucleo-idw01m1/SPWFSAxx.cpp Show annotated file Show diff for this revision Revisions of this file
wifi-x-nucleo-idw01m1/SPWFSAxx.h Show annotated file Show diff for this revision Revisions of this file
wifi-x-nucleo-idw01m1/SpwfSAInterface.cpp Show annotated file Show diff for this revision Revisions of this file
wifi-x-nucleo-idw01m1/SpwfSAInterface.h Show annotated file Show diff for this revision Revisions of this file
wifi-x-nucleo-idw01m1/mbed_app_idw01m1.json Show annotated file Show diff for this revision Revisions of this file
wifi-x-nucleo-idw01m1/mbed_app_idw04a1.json Show annotated file Show diff for this revision Revisions of this file
wifi-x-nucleo-idw01m1/mbed_lib.json Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Jenkinsfile	Wed Oct 28 07:42:46 2020 +0000
@@ -0,0 +1,94 @@
+properties ([[$class: 'ParametersDefinitionProperty', parameterDefinitions: [
+  [$class: 'StringParameterDefinition', name: 'mbed_os_revision', defaultValue: '', description: 'Revision of mbed-os to build. Use format "pull/PR-NUMBER/head" to access mbed-os PR']
+  ]]])
+
+if (params.mbed_os_revision == '') {
+  echo 'Use mbed OS revision from mbed-os.lib'
+} else {
+  echo "Use mbed OS revisiong ${params.mbed_os_revision}"
+  if (params.mbed_os_revision.matches('pull/\\d+/head')) {
+    echo "Revision is a Pull Request"
+  }
+}
+
+// List of targets with supported RF shields to compile
+def targets = [
+  "UBLOX_EVK_ODIN_W2": ["builtin"],
+  "NUCLEO_F401RE": ["WIFI_IDW0XX1"],
+  "DISCO_L475VG_IOT01A": ["WIFI_ISM43362"],
+  "DISCO_F413ZH": ["WIFI_ISM43362"]
+  ]
+
+// Map toolchains to compilers
+def toolchains = [
+  ARM: "armcc",
+  GCC_ARM: "arm-none-eabi-gcc",
+  IAR: "IAR-linux"
+  ]
+
+// Supported RF shields
+def radioshields = [
+  "builtin",
+  "WIFI_IDW0XX1"
+  ]
+
+def stepsForParallel = [:]
+
+// Jenkins pipeline does not support map.each, we need to use oldschool for loop
+for (int i = 0; i < targets.size(); i++) {
+    for(int j = 0; j < toolchains.size(); j++) {
+        for(int k = 0; k < radioshields.size(); k++) {
+            def target = targets.keySet().asList().get(i)
+            def allowed_shields = targets.get(target)
+            def toolchain = toolchains.keySet().asList().get(j)
+            def compilerLabel = toolchains.get(toolchain)
+            def radioshield = radioshields.get(k)
+
+            def stepName = "${target} ${toolchain} ${radioshield}"
+            if(allowed_shields.contains(radioshield)) {
+              stepsForParallel[stepName] = buildStep(target, compilerLabel, toolchain, radioshield)
+            }
+        }
+    }
+}
+
+timestamps {
+  parallel stepsForParallel
+}
+
+def buildStep(target, compilerLabel, toolchain, radioShield) {
+  return {
+    stage ("${target}_${compilerLabel}_${radioShield}") {
+      node ("${compilerLabel}") {
+        deleteDir()
+        dir("mbed-os-example-wifi") {
+          checkout scm
+          def config_file = "mbed_app.json"
+
+          if ("${radioShield}" != "internal") {
+            // Replace default rf shield
+            execute("sed -i 's/\"value\": \"internal\"/\"value\": \"${radioShield}\"/' ${config_file}")
+          }
+
+          // Set mbed-os to revision received as parameter
+          execute ("mbed deploy --protocol ssh")
+          if (params.mbed_os_revision != '') {
+            dir ("mbed-os") {
+              if (params.mbed_os_revision.matches('pull/\\d+/head')) {
+                execute("git fetch origin ${params.mbed_os_revision}:PR")
+                execute("git checkout PR")
+              } else {
+                execute ("git checkout ${params.mbed_os_revision}")
+              }
+            }
+          }
+          execute("mbed new .")
+          execute ("mbed compile --build out/${target}_${toolchain}_${radioShield}/ -m ${target} -t ${toolchain} -c --app-config ${config_file}")
+        }
+        stash name: "${target}_${toolchain}_${radioShield}", includes: '**/mbed-os-example-wifi.bin'
+        archive '**/mbed-os-example-wifi.bin'
+        step([$class: 'WsCleanup'])
+      }
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LICENSE	Wed Oct 28 07:42:46 2020 +0000
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "{}"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright {yyyy} {name of copyright owner}
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/README.md	Wed Oct 28 07:42:46 2020 +0000
@@ -0,0 +1,104 @@
+# mbed-os-example-wifi #
+
+Wi-Fi example for Mbed OS
+
+## Getting started with the Wi-Fi API ##
+
+This is an example of a Wi-Fi application using the Wi-Fi and network socket APIs that [Mbed OS](https://github.com/ARMmbed/mbed-os) provides.
+
+The program brings up the Wi-Fi and the underlying network interface and uses it to scan available networks, connects to a network, prints interface and connection details and performs an HTTP operation.
+
+For more information about Wi-Fi APIs, please visit the [Mbed OS Wi-Fi](https://os.mbed.com/docs/latest/reference/wi-fi.html) documentation.
+
+### Supported hardware ###
+
+* [NUCLEO-F401RE](https://os.mbed.com/platforms/ST-Nucleo-F401RE/) with [X-NUCLEO-IDW04A1](http://www.st.com/content/st_com/en/products/ecosystems/stm32-open-development-environment/stm32-nucleo-expansion-boards/stm32-ode-connect-hw/x-nucleo-idw04a1.html) Wi-Fi expansion board using pins D8 and D2 _(of the Arduino connector)_.
+* [NUCLEO-F401RE](https://os.mbed.com/platforms/ST-Nucleo-F401RE/) with [X-NUCLEO-IDW01M1](https://os.mbed.com/components/X-NUCLEO-IDW01M1/) Wi-Fi expansion board using pins PA_9 and PA_10 _(of the Morpho connector)_.
+* [DISCO_L475VG_IOT01A](https://os.mbed.com/platforms/ST-Discovery-L475E-IOT01A/) with ISM43362 built-in module
+* [DISCO_F413ZH](https://os.mbed.com/platforms/ST-Discovery-F413H/) with ISM43362 built-in module
+* Other Mbed targets with  [X-NUCLEO-IDW04A1](http://www.st.com/content/st_com/en/products/ecosystems/stm32-open-development-environment/stm32-nucleo-expansion-boards/stm32-ode-connect-hw/x-nucleo-idw04a1.html) or [X-NUCLEO-IDW01M1](https://os.mbed.com/components/X-NUCLEO-IDW01M1/) expansion board.
+  *(The Mbed target board the Wi-Fi shield connects to shouldn't have any other network interface, for example Ethernet.)*
+
+#### Connecting the X-NUCLEO-IDW0XX1 ####
+
+To connect the [X-NUCLEO-IDW04A1](http://www.st.com/content/st_com/en/products/ecosystems/stm32-open-development-environment/stm32-nucleo-expansion-boards/stm32-ode-connect-hw/x-nucleo-idw04a1.html) or [X-NUCLEO-IDW01M1](https://developer.mbed.org/components/X-NUCLEO-IDW01M1/) expansion board to your NUCLEO development board, plug the expansion board on top of the NUCLEO board using the Arduino or Morpho connector.
+
+##  Getting started ##
+
+1. Import the example.
+
+   ```
+   mbed import mbed-os-example-wifi
+   cd mbed-os-example-wifi
+   ```
+   
+2. Configure the Wi-Fi shield to use.
+
+   Edit ```mbed_app.json``` to include the correct Wi-Fi shield, SSID and password:
+
+   ```
+       "config": {
+ 	  "wifi-shield": {
+               "help": "Options are WIFI_IDW0XX1",
+               "value": "WIFI_IDW0XX1"
+        	  },
+           "wifi-ssid": {
+               "help": "WiFi SSID",
+               "value": "\"SSID\""
+           },
+           "wifi-password": {
+               "help": "WiFi Password",
+               "value": "\"Password\""
+           }
+       },
+   ```
+
+   Sample ```mbed_app.json``` files are provided for X-NUCLEO-IDW04A1 (```mbed_app_idw04a1.json```),  X-NUCLEO-IDW01M1 (```mbed_app_idw01m1```), DISCO_L475VG_IOT01A/ISM43362 (```mbed_app_ism43362.json```) and DISCO_F413ZH/ISM43362 (```mbed_app_ism43362.json```)
+   
+   For built-in Wi-Fi, ignore the value of `wifi-shield`.
+
+3. Compile and generate binary.
+
+   For example, for `GCC`:
+
+   ```
+   mbed compile -t GCC_ARM -m UBLOX_EVK_ODIN_W2
+   ```
+   
+ 4. Open a serial console session with the target platform using the following parameters:
+ 
+    * **Baud rate:** 9600
+    * **Data bits:** 8
+    * **Stop bits:** 1
+    * **Parity:** None
+ 
+ 5. Copy or drag the application `mbed-os-example-wifi.bin` in the folder `mbed-os-example-wifi/BUILD/<TARGET NAME>/<PLATFORM NAME>` onto the target board.
+ 
+ 6. The serial console should display a similar output to below, indicating a successful Wi-Fi connection:
+ 
+ ```
+ WiFi example
+
+Scan:
+Network: Dave Hot Spot secured: Unknown BSSID: 00:01:02:03:04:05 RSSI: -58 Ch: 1
+1 network available.
+
+Connecting...
+Success
+
+MAC: 00:01:02:03:04:05
+IP: 192.168.0.5
+Netmask: 255.255.255.0
+Gateway: 192.168.0.1
+RSSI: -27
+
+Sending HTTP request to www.arm.com...
+sent 38 [GET / HTTP/1.1]
+recv 64 [HTTP/1.1 301 Moved Permanently]
+
+Done
+```
+
+## Troubleshooting
+
+If you have problems, you can review the [documentation](https://os.mbed.com/docs/latest/tutorials/debugging.html) for suggestions on what could be wrong and how to fix it.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Oct 28 07:42:46 2020 +0000
@@ -0,0 +1,277 @@
+/* WiFi Example
+ * Copyright (c) 2018 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mbed.h"
+#include "TCPSocket.h"
+#include <DigitalIn.h>
+ 
+#define WIFI_IDW0XX1    2
+
+#define TS_DEVICE "StmWifi" //mettre le nom de votre canal TS
+#define thingspeak_APIkey_write "SOSW9VB0YR0D0GF8" //mettre la clé d'écriture de votre canal TS
+#define thingspeak_APIkey_read "YEBSWYV532L13T23" //mettre la clé lecture de votre canal TS
+
+
+#if (defined(TARGET_DISCO_L475VG_IOT01A) || defined(TARGET_DISCO_F413ZH))
+#include "ISM43362Interface.h"
+
+ISM43362Interface wifi(MBED_CONF_APP_WIFI_SPI_MOSI, MBED_CONF_APP_WIFI_SPI_MISO, MBED_CONF_APP_WIFI_SPI_SCLK, MBED_CONF_APP_WIFI_SPI_NSS, MBED_CONF_APP_WIFI_RESET, MBED_CONF_APP_WIFI_DATAREADY, MBED_CONF_APP_WIFI_WAKEUP, false);
+
+#else // External WiFi modules
+
+#if MBED_CONF_APP_WIFI_SHIELD == WIFI_IDW0XX1
+#include "SpwfSAInterface.h"
+SpwfSAInterface wifi(MBED_CONF_APP_WIFI_TX, MBED_CONF_APP_WIFI_RX);
+#endif // MBED_CONF_APP_WIFI_SHIELD == WIFI_IDW0XX1
+
+#endif
+char hostName[] = "8406e1ca8b3e.ngrok.io";
+char cardId[] = "carte_9";
+char sensorId[256];
+DigitalIn sensorIn(D8);
+
+int sensorState = 0;
+const char *sec2str(nsapi_security_t sec)
+{
+    switch (sec) {
+        case NSAPI_SECURITY_NONE:
+            return "None";
+        case NSAPI_SECURITY_WEP:
+            return "WEP";
+        case NSAPI_SECURITY_WPA:
+            return "WPA";
+        case NSAPI_SECURITY_WPA2:
+            return "WPA2";
+        case NSAPI_SECURITY_WPA_WPA2:
+            return "WPA/WPA2";
+        case NSAPI_SECURITY_UNKNOWN:
+        default:
+            return "Unknown";
+    }
+}
+
+int scan_wifi(WiFiInterface *wifi)
+{
+    WiFiAccessPoint *ap;
+
+    printf("Scan:\n");
+
+    int count = wifi->scan(NULL,0);
+    printf("%d networks available.\n", count);
+
+    /* Limit number of network arbitrary to 15 */
+    count = count < 15 ? count : 15;
+
+    ap = new WiFiAccessPoint[count];
+    count = wifi->scan(ap, count);
+    for (int i = 0; i < count; i++)
+    {
+        printf("Network: %s secured: %s BSSID: %hhX:%hhX:%hhX:%hhx:%hhx:%hhx RSSI: %hhd Ch: %hhd\n", ap[i].get_ssid(),
+               sec2str(ap[i].get_security()), ap[i].get_bssid()[0], ap[i].get_bssid()[1], ap[i].get_bssid()[2],
+               ap[i].get_bssid()[3], ap[i].get_bssid()[4], ap[i].get_bssid()[5], ap[i].get_rssi(), ap[i].get_channel());
+    }
+
+    delete[] ap;
+    return count;
+}
+void http_demo(NetworkInterface *net)
+{
+    TCPSocket socket;
+    nsapi_error_t response;
+
+    printf("Sending HTTP request to ngrok.io...\n");
+
+    // Open a socket on the network interface, and create a TCP connection to www.arm.com
+    socket.open(net);
+    response = socket.connect(hostName, 80);
+    if(0 != response) {
+        printf("Error connecting: %d\n", response);
+        socket.close();
+        return;
+    }
+
+    // Send a simple http request
+    char sbuffer[256];
+    sprintf(sbuffer, "GET /api/v1/sensor/identify HTTP/1.1\r\nHost: %s\r\n\r\n", hostName);
+    nsapi_size_t size = strlen(sbuffer);
+    response = 0;
+    while(size)
+    {
+        response = socket.send(sbuffer+response, size);
+        if (response < 0) {
+            printf("Error sending data: %d\n", response);
+            socket.close();
+            return;
+        } else {
+            size -= response;
+            // Check if entire message was sent or not
+            printf("sent %d [%.*s]\n", response, strstr(sbuffer, "\r\n")-sbuffer, sbuffer);
+        }
+    }
+
+    // Recieve a simple http response and print out the response line
+    char rbuffer[64];
+    response = socket.recv(rbuffer, sizeof rbuffer);
+    if (response < 0) {
+        printf("Error receiving data: %d\n", response);
+    } else {
+        printf("recv %d [%.*s]\n", response, strstr(rbuffer, "\r\n")-rbuffer, rbuffer);
+    }
+
+    // Close the socket to return its memory and bring down the network interface
+    socket.close();
+}
+void authentificate(NetworkInterface *net){
+    TCPSocket socket;
+    nsapi_error_t response;
+
+    printf("Sending HTTP request to host...\n");
+
+    // Open a socket on the network interface, and create a TCP connection to www.arm.com
+    socket.open(net);
+    response = socket.connect(hostName, 80);
+    if(0 != response) {
+        printf("Error connecting: %d\n", response);
+        socket.close();
+        return;
+    }
+
+    // Send a simple http request
+    char sbuffer[256];
+    sprintf(sbuffer, "GET /api/v1/sensor/identify?sensorId=%s HTTP/1.1\r\nHost: %s\r\n\r\n", cardId,hostName);
+    nsapi_size_t size = strlen(sbuffer);
+    response = 0;
+    while(size)
+    {
+        response = socket.send(sbuffer+response, size);
+        if (response < 0) {
+            printf("Error sending data: %d\n", response);
+            socket.close();
+            return;
+        } else {
+            size -= response;
+            // Check if entire message was sent or not
+            printf("sent %d [%.*s]\n", response, strstr(sbuffer, "\r\n")-sbuffer, sbuffer);
+        }
+    }
+
+    // Recieve a simple http response and print out the response line
+    char rbuffer[64];
+    response = socket.recv(rbuffer, sizeof rbuffer);
+    if (response < 0) {
+        printf("Error receiving data: %d\n", response);
+    } else {
+        printf("recv %d [%.*s]\n", response, strstr(rbuffer, "\r\n")-rbuffer, rbuffer);
+    }
+
+    // Close the socket to return its memory and bring down the network interface
+    socket.close();
+}
+void updateStatus(NetworkInterface *net){
+    TCPSocket socket;
+    nsapi_error_t response;
+
+    printf("Sending HTTP request to ngrok.io...\n");
+
+    // Open a socket on the network interface, and create a TCP connection to www.arm.com
+    socket.open(net);
+    response = socket.connect(hostName, 80);
+    if(0 != response) {
+        printf("Error connecting: %d\n", response);
+        socket.close();
+        return;
+    }
+
+    // Send a simple http request
+    char sbuffer[256];
+    if(!sensorState){
+        sprintf(sbuffer, "GET /api/v1/sensor/update?sensorId=%s&state=1 HTTP/1.1\r\nHost: %s\r\n\r\n", cardId, hostName);
+    } else {
+        sprintf(sbuffer, "GET /api/v1/sensor/update?sensorId=%s&state= HTTP/1.1\r\nHost: %s\r\n\r\n", cardId , hostName);
+        
+    }
+    // sprintf(sbuffer, "GET /api/v1/sensor/update?sensorId=%s&state=%d HTTP/1.1\r\nHost: %s\r\n\r\n", cardId, sensorState, hostName);
+    nsapi_size_t size = strlen(sbuffer);
+    response = 0;
+    while(size)
+    {
+        response = socket.send(sbuffer+response, size);
+        if (response < 0) {
+            printf("Error sending data: %d\n", response);
+            socket.close();
+            return;
+        } else {
+            size -= response;
+            // Check if entire message was sent or not
+            printf("sent %d [%.*s]\n", response, strstr(sbuffer, "\r\n")-sbuffer, sbuffer);
+        }
+    }
+
+    // Recieve a simple http response and print out the response line
+    char rbuffer[64];
+    response = socket.recv(rbuffer, sizeof rbuffer);
+    if (response < 0) {
+        printf("Error receiving data: %d\n", response);
+    } else {
+        printf("recv %d [%.*s]\n", response, strstr(rbuffer, "\r\n")-rbuffer, rbuffer);
+    }
+
+    // Close the socket to return its memory and bring down the network interface
+    socket.close();
+}
+
+int main()
+{   
+    int previousState;
+    int count = 0;
+
+    printf("WiFi connect attempt\n\n");
+    count = scan_wifi(&wifi);
+    if (count == 0) {
+        printf("No WIFI APNs found - can't continue further.\n");
+        //return -1;
+    }
+    
+    
+    printf("\nConnecting to %s...\n", MBED_CONF_APP_WIFI_SSID);
+    int ret = wifi.connect(MBED_CONF_APP_WIFI_SSID, MBED_CONF_APP_WIFI_PASSWORD, NSAPI_SECURITY_WPA_WPA2);
+    if (ret != 0) {
+        printf("\nConnection error\n");
+        return -1;
+    }
+    printf("Success\n\n");
+    printf("MAC: %s\n", wifi.get_mac_address());
+    printf("IP: %s\n", wifi.get_ip_address());
+    printf("Netmask: %s\n", wifi.get_netmask());
+    printf("Gateway: %s\n", wifi.get_gateway());
+    printf("RSSI: %d\n\n", wifi.get_rssi());
+
+    http_demo(&wifi);
+    authentificate(&wifi);
+    sensorState =  sensorIn.read();
+    updateStatus(&wifi);
+    while(true){
+        previousState = sensorState;
+        sensorState =  sensorIn.read();
+        if(previousState != sensorState){
+            printf("Sensor = %d\n",sensorState);
+            updateStatus(&wifi);
+        }
+        // wait(1.0); 
+        //printf("Sensor %s", digitalRead(9));
+    }
+    wifi.disconnect();
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-os.lib	Wed Oct 28 07:42:46 2020 +0000
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/mbed-os/#569159b784f70feaa32ce226aaca896fb83452f7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed_app.json	Wed Oct 28 07:42:46 2020 +0000
@@ -0,0 +1,83 @@
+{
+    "config": {
+        "wifi-shield": {
+            "help": "Options are internal, WIFI_IDW0XX1",
+            "value": "internal"
+        },
+        "wifi-ssid": {
+            "help": "Wifi SSID",
+            "value": "\"dlink-0AE0\""
+        },
+        "wifi-password": {
+            "help": "WiFi Password",
+            "value": "\"hpdyx89124\""
+        },
+        "wifi-tx": {
+            "help": "TX pin for serial connection to external device",
+            "value": "D1"
+        },
+        "wifi-rx": {
+            "help": "RX pin for serial connection to external device",
+            "value": "D0"
+        },
+        "wifi-spi_miso": {
+            "help": "SPI-MISO connection to external device",
+            "value": "PC_11"
+        },
+        "wifi-spi_mosi": {
+            "help": "SPI-MOSI connection to external device",
+            "value": "PC_12"
+        },
+        "wifi-spi_sclk": {
+            "help": "SPI-CLOCK connection to external device",
+            "value": "PC_10"
+        },
+        "wifi-spi_nss": {
+            "help": "SPI chip select of external device",
+            "value": "PE_0"
+        },
+        "wifi-reset": {
+            "help": "WIFI module reset pin",
+            "value": "PE_8"
+        },
+        "wifi-dataready": {
+            "help": "WIFI module data ready pin",
+            "value": "PE_1"
+        },
+        "wifi-wakeup": {
+            "help": "WIFI module wakeup pin",
+            "value": "PB_12"
+        }
+    },
+    "target_overrides": {
+        "*": {
+            "platform.stdio-convert-newlines": true
+        },
+        "NUCLEO_L476RG": {
+            "wifi-tx": "D8",
+            "wifi-rx": "D2"
+        },
+        "NUCLEO_F401RE": {
+            "wifi-tx": "D8",
+            "wifi-rx": "D2"
+        },
+        "DISCO_L475VG_IOT1A": {
+            "wifi-spi_miso": "PC_11",
+            "wifi-spi_mosi": "PC_12",
+            "wifi-spi_sclk": "PC_10",
+            "wifi-spi_nss": "PE_0",
+            "wifi-reset": "PE_8",
+            "wifi-dataready": "PE_1",
+            "wifi-wakeup": "PB_12"
+        },
+        "DISCO_F413ZH": {
+            "wifi-spi_miso": "PB_4",
+            "wifi-spi_mosi": "PB_5",
+            "wifi-spi_sclk": "PB_12",
+            "wifi-spi_nss": "PG_11",
+            "wifi-reset": "PH_1",
+            "wifi-dataready": "PG_12",
+            "wifi-wakeup": "PB_15"
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed_app_idw01m1.json	Wed Oct 28 07:42:46 2020 +0000
@@ -0,0 +1,35 @@
+{
+    "config": {
+	"wifi-shield": {
+            "help": "Options are internal, WIFI_ESP8266, WIFI_IDW0XX1",
+            "value": "WIFI_IDW0XX1"
+	},
+        "wifi-ssid": {
+            "help": "WiFi SSID",
+            "value": "\"SSID\""
+        },
+        "wifi-password": {
+            "help": "WiFi Password",
+            "value": "\"PASSWORD\""
+        },
+        "wifi-tx": {
+            "help": "TX pin for serial connection to external device",
+            "value": "PA_9"
+        },
+        "wifi-rx": {
+            "help": "RX pin for serial connection to external device",
+            "value": "PA_10"
+        }
+    },
+    "target_overrides": {
+        "*": {
+            "platform.stdio-convert-newlines": true,
+            "idw0xx1.expansion-board": "IDW01M1",
+	    "drivers.uart-serial-txbuf-size": 730,
+	    "drivers.uart-serial-rxbuf-size": 730
+        },
+        "UBLOX_EVK_ODIN_W2": {
+            "target.device_has": ["EMAC"]
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed_app_idw04a1.json	Wed Oct 28 07:42:46 2020 +0000
@@ -0,0 +1,36 @@
+{
+    "config": {
+	"wifi-shield": {
+            "help": "Options are internal, WIFI_ESP8266, WIFI_IDW0XX1",
+            "value": "WIFI_IDW0XX1"
+	},
+        "wifi-ssid": {
+            "help": "WiFi SSID",
+            "value": "\"SSID\""
+        },
+        "wifi-password": {
+            "help": "WiFi Password",
+            "value": "\"PASSWORD\""
+        },
+        "wifi-tx": {
+            "help": "TX pin for serial connection to external device",
+            "value": "D8"
+        },
+        "wifi-rx": {
+            "help": "RX pin for serial connection to external device",
+            "value": "D2"
+        }
+    },
+    "target_overrides": {
+        "*": {
+            "platform.stdio-convert-newlines": true,
+            "idw0xx1.expansion-board": "IDW04A1",
+	    "drivers.uart-serial-txbuf-size": 750,
+	    "drivers.uart-serial-rxbuf-size": 750
+        },
+	"UBLOX_EVK_ODIN_W2": {
+            "target.device_has": ["EMAC"]
+	}
+    },
+    "macros": ["IDW04A1_WIFI_HW_BUG_WA"]
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed_app_ism43362.json	Wed Oct 28 07:42:46 2020 +0000
@@ -0,0 +1,86 @@
+{
+    "config": {
+        "wifi-shield": {
+            "help": "Options are internal, WIFI_ESP8266, WIFI_IDW0XX1",
+            "value": "internal"
+        },
+        "wifi-ssid": {
+            "help": "WiFi SSID",
+            "value": "\"SSID\""
+        },
+        "wifi-password": {
+            "help": "WiFi Password",
+            "value": "\"PASSWORD\""
+        },
+        "wifi-tx": {
+            "help": "TX pin for serial connection to external device",
+            "value": "D1"
+        },
+        "wifi-rx": {
+            "help": "RX pin for serial connection to external device",
+            "value": "D0"
+        },
+        "wifi-spi_miso": {
+            "help": "SPI-MISO connection to external device",
+            "value": "PC_11"
+        },
+        "wifi-spi_mosi": {
+            "help": "SPI-MOSI connection to external device",
+            "value": "PC_12"
+        },
+        "wifi-spi_sclk": {
+            "help": "SPI-CLOCK connection to external device",
+            "value": "PC_10"
+        },
+        "wifi-spi_nss": {
+            "help": "SPI chip select of external device",
+            "value": "PE_0"
+        },
+        "wifi-reset": {
+            "help": "WIFI module reset pin",
+            "value": "PE_8"
+        },
+        "wifi-dataready": {
+            "help": "WIFI module data ready pin",
+            "value": "PE_1"
+        },
+        "wifi-wakeup": {
+            "help": "WIFI module wakeup pin",
+            "value": "PB_12"
+        }
+    },
+    "target_overrides": {
+        "*": {
+            "platform.stdio-convert-newlines": true
+        },
+        "UBLOX_EVK_ODIN_W2": {
+            "target.device_has": ["EMAC"]
+        },
+        "NUCLEO_L476RG": {
+            "wifi-tx": "D8",
+            "wifi-rx": "D2"
+        },
+        "NUCLEO_F401RE": {
+            "wifi-tx": "D8",
+            "wifi-rx": "D2"
+        },
+        "DISCO_L475VG_IOT1A": {
+            "wifi-spi_miso": "PC_11",
+            "wifi-spi_mosi": "PC_12",
+            "wifi-spi_sclk": "PC_10",
+            "wifi-spi_nss": "PE_0",
+            "wifi-reset": "PE_8",
+            "wifi-dataready": "PE_1",
+            "wifi-wakeup": "PB_12"
+        },
+        "DISCO_F413ZH": {
+            "wifi-spi_miso": "PB_4",
+            "wifi-spi_mosi": "PB_5",
+            "wifi-spi_sclk": "PB_12",
+            "wifi-spi_nss": "PG_11",
+            "wifi-reset": "PH_1",
+            "wifi-dataready": "PG_12",
+            "wifi-wakeup": "PB_15"
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362.lib	Wed Oct 28 07:42:46 2020 +0000
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/wifi-ism43362/#e4ecc27e87d96072f7df62a25ef007986dc95c4e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/ISM43362/ATParser/ATParser.cpp	Wed Oct 28 07:42:46 2020 +0000
@@ -0,0 +1,427 @@
+/* Copyright (c) 2015 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @section DESCRIPTION
+ *
+ * Parser for the AT command syntax
+ *
+ */
+
+#include "ATParser.h"
+#include "mbed_debug.h"
+
+#ifdef LF
+#undef LF
+#define LF  10
+#else
+#define LF  10
+#endif
+
+#ifdef CR
+#undef CR
+#define CR  13
+#else
+#define CR  13
+#endif
+#define MIN(a,b) (((a)<(b))?(a):(b))
+
+#define dbg_on 0
+//#define TRACE_AT_DATA 1
+
+// getc/putc handling with timeouts
+int ATParser::putc(char c)
+{
+    return _serial_spi->putc(c);
+}
+
+int ATParser::getc()
+{
+    return _serial_spi->getc();
+}
+
+void ATParser::flush()
+{
+    _bufferMutex.lock();
+    while (_serial_spi->readable()) {
+        _serial_spi->getc();
+    }
+    _bufferMutex.unlock();
+}
+
+// read/write handling with timeouts
+int ATParser::write(const char *data, int size_of_data, int size_in_buff)
+{
+    int i = 0;
+    _bufferMutex.lock();
+    for ( ; i < size_of_data; i++) {
+        if (putc(data[i]) < 0) {
+            _bufferMutex.unlock();
+            return -1;
+        }
+    }
+
+    _serial_spi->buffsend(size_of_data + size_in_buff);
+    _bufferMutex.unlock();
+    return (size_of_data + size_in_buff);
+}
+
+int ATParser::read(char *data)
+{
+    int readsize;
+    int i = 0;
+
+    _bufferMutex.lock();
+
+    //this->flush();
+    if(!_serial_spi->readable()) {
+        readsize = _serial_spi->read();
+    } else {
+        error("Pending data when reading from WIFI\r\n");
+        return -1;
+    }
+
+    debug_if(dbg_on, "Avail in SPI %d\r\n", readsize);
+
+    if ( readsize < 0) {
+        _bufferMutex.unlock();
+        return -1;
+    }
+
+    for (i = 0 ; i < readsize; i++) {
+       int c = getc();
+       if (c < 0) {
+           _bufferMutex.unlock();
+           return -1;
+       }
+       data[i] = c;
+    }
+
+#if TRACE_AT_DATA
+    debug_if(dbg_on, "AT<< %d BYTES\r\n", readsize);
+    for (i = 0; i < readsize; i++) {
+         debug_if(dbg_on, "%2X ", data[i]);
+    }
+    debug_if(dbg_on, "\r\n");
+#endif
+
+    _bufferMutex.unlock();
+
+    return (readsize);
+}
+
+// printf/scanf handling
+int ATParser::vprintf(const char *format, va_list args)
+{
+    _bufferMutex.lock();
+    if (vsprintf(_buffer, format, args) < 0) {
+        _bufferMutex.unlock();
+        return false;
+    }
+
+    int i = 0;
+    for ( ; _buffer[i]; i++) {
+        if (putc(_buffer[i]) < 0) {
+            _bufferMutex.unlock();
+            return -1;
+        }
+    }
+    _bufferMutex.unlock();
+
+    return i;
+}
+
+int ATParser::vscanf(const char *format, va_list args)
+{
+    // Since format is const, we need to copy it into our buffer to
+    // add the line's null terminator and clobber value-matches with asterisks.
+    //
+    // We just use the beginning of the buffer to avoid unnecessary allocations.
+    int i = 0;
+    int offset = 0;
+
+    _bufferMutex.lock();
+
+    while (format[i]) {
+        if (format[i] == '%' && format[i+1] != '%' && format[i+1] != '*') {
+            _buffer[offset++] = '%';
+            _buffer[offset++] = '*';
+            i++;
+        } else {
+            _buffer[offset++] = format[i++];
+        }
+    }
+
+    // Scanf has very poor support for catching errors
+    // fortunately, we can abuse the %n specifier to determine
+    // if the entire string was matched.
+    _buffer[offset++] = '%';
+    _buffer[offset++] = 'n';
+    _buffer[offset++] = 0;
+
+    // To workaround scanf's lack of error reporting, we actually
+    // make two passes. One checks the validity with the modified
+    // format string that only stores the matched characters (%n).
+    // The other reads in the actual matched values.
+    //
+    // We keep trying the match until we succeed or some other error
+    // derails us.
+    int j = 0;
+
+    while (true) {
+        // Ran out of space
+        if (j+1 >= _buffer_size - offset) {
+            _bufferMutex.unlock();
+            return false;
+        }
+        // Recieve next character
+        int c = getc();
+        if (c < 0) {
+            _bufferMutex.unlock();
+            return -1;
+        }
+        _buffer[offset + j++] = c;
+        _buffer[offset + j] = 0;
+
+        // Check for match
+        int count = -1;
+        sscanf(_buffer+offset, _buffer, &count);
+
+        // We only succeed if all characters in the response are matched
+        if (count == j) {
+            // Store the found results
+            vsscanf(_buffer+offset, format, args);
+            _bufferMutex.unlock();
+            return j;
+        }
+    }
+}
+
+
+// Command parsing with line handling
+bool ATParser::vsend(const char *command, va_list args)
+{
+    int i=0, j=0;
+    _bufferMutex.lock();
+    // Create and send command
+    if (vsprintf(_buffer, command, args) < 0) {
+        _bufferMutex.unlock();
+        return false;
+    }
+    /* get buffer length */
+    for (i = 0; _buffer[i]; i++) {
+    }
+
+    for (j=0; _delimiter[j]; j++) {
+        _buffer[i+j] = _delimiter[j];
+    }
+    _buffer[i+j]=0; // only to get a clean debug log
+    
+    bool ret = !(_serial_spi->buffwrite(_buffer, i+j) < 0);
+
+    debug_if(dbg_on, "AT> %s\n", _buffer);
+    _bufferMutex.unlock();
+    return ret;
+}
+
+bool ATParser::vrecv(const char *response, va_list args)
+{
+    _bufferMutex.lock();
+    /* Read from the wifi module, fill _rxbuffer */
+    //this->flush();
+    if(!_serial_spi->readable()) {
+         debug_if(dbg_on, "NO DATA, read again\r\n");
+        if (_serial_spi->read() < 0) {
+            return false;
+        }
+    } else {
+         debug_if(dbg_on, "Pending data\r\n");
+    }
+restart:
+    _aborted = false;
+    // Iterate through each line in the expected response
+    while (response[0]) {
+        // Since response is const, we need to copy it into our buffer to
+        // add the line's null terminator and clobber value-matches with asterisks.
+        //
+        // We just use the beginning of the buffer to avoid unnecessary allocations.
+        int i = 0;
+        int offset = 0;
+        bool whole_line_wanted = false;
+
+        while (response[i]) {
+            if (response[i] == '%' && response[i+1] != '%' && response[i+1] != '*') {
+                _buffer[offset++] = '%';
+                _buffer[offset++] = '*';
+                i++;
+            } else {
+                _buffer[offset++] = response[i++];
+                // Find linebreaks, taking care not to be fooled if they're in a %[^\n] conversion specification
+                if (response[i - 1] == '\n' && !(i >= 3 && response[i-3] == '[' && response[i-2] == '^')) {
+                    whole_line_wanted = true;
+                    break;
+                }
+            }
+        }
+
+        // Scanf has very poor support for catching errors
+        // fortunately, we can abuse the %n specifier to determine
+        // if the entire string was matched.
+        _buffer[offset++] = '%';
+        _buffer[offset++] = 'n';
+        _buffer[offset++] = 0;
+
+        debug_if(dbg_on, "AT? ====%s====\n", _buffer);
+        // To workaround scanf's lack of error reporting, we actually
+        // make two passes. One checks the validity with the modified
+        // format string that only stores the matched characters (%n).
+        // The other reads in the actual matched values.
+        //
+        // We keep trying the match until we succeed or some other error
+        // derails us.
+        int j = 0;
+
+        while (true) {
+            // Recieve next character
+            int c = getc();
+            if (c < 0) {
+                debug_if(dbg_on, "AT(Timeout)\n");
+                _bufferMutex.unlock();
+                return false;
+            }
+
+#if TRACE_AT_DATA
+             debug_if(dbg_on, "%2X ", c);
+#endif
+            _buffer[offset + j++] = c;
+            _buffer[offset + j] = 0;
+
+            // Check for oob data
+            for (struct oob *oob = _oobs; oob; oob = oob->next) {
+                if ((unsigned)j == oob->len && memcmp(
+                        oob->prefix, _buffer+offset, oob->len) == 0) {
+                    debug_if(dbg_on, "AT! %s\n", oob->prefix);
+                    oob->cb();
+
+                    if (_aborted) {
+                        debug_if(dbg_on, "AT(Aborted)\n");
+                        _bufferMutex.unlock();
+                        return false;
+                    }
+                    // oob may have corrupted non-reentrant buffer,
+                    // so we need to set it up again
+                    goto restart;
+                }
+            }
+
+            // Check for match
+            int count = -1;
+            if (whole_line_wanted && c != '\n' && c != ' ') {
+                // Don't attempt scanning until we get delimiter if they included it in format
+                // This allows recv("Foo: %s\n") to work, and not match with just the first character of a string
+                // (scanf does not itself match whitespace in its format string, so \n is not significant to it)
+            } else {
+                sscanf(_buffer+offset, _buffer, &count);
+            }
+
+            // We only succeed if all characters in the response are matched
+            if (count == j) {
+                debug_if(dbg_on, "AT= ====%s====\n", _buffer + offset);
+                // Reuse the front end of the buffer
+                memcpy(_buffer, response, i);
+                _buffer[i] = 0;
+
+                // Store the found results
+                vsscanf(_buffer+offset, _buffer, args);
+
+                // Jump to next line and continue parsing
+                response += i;
+                break;
+            }
+
+            // Clear the buffer when we hit a newline or ran out of space
+            // running out of space usually means we ran into binary data
+            if ((c == '\n') ) {
+                debug_if(dbg_on, "New line AT<<< %s", _buffer+offset);
+                j = 0;
+            }
+            if ((j + 1 >= (_buffer_size - offset))) {
+
+                debug_if(dbg_on, "Out of space AT<<< %s, j=%d", _buffer+offset, j);
+                j = 0;
+            }
+        }
+    }
+
+    _bufferMutex.unlock();
+
+    return true;
+}
+
+
+// Mapping to vararg functions
+int ATParser::printf(const char *format, ...)
+{
+    va_list args;
+    va_start(args, format);
+    int res = vprintf(format, args);
+    va_end(args);
+    return res;
+}
+
+int ATParser::scanf(const char *format, ...)
+{
+    va_list args;
+    va_start(args, format);
+    int res = vscanf(format, args);
+    va_end(args);
+    return res;
+}
+
+bool ATParser::send(const char *command, ...)
+{
+    va_list args;
+    va_start(args, command);
+    bool res = vsend(command, args);
+    va_end(args);
+    return res;
+}
+
+bool ATParser::recv(const char *response, ...)
+{
+    va_list args;
+    va_start(args, response);
+    bool res = vrecv(response, args);
+    va_end(args);
+    return res;
+}
+
+
+// oob registration
+void ATParser::oob(const char *prefix, Callback<void()> cb)
+{
+    struct oob *oob = new struct oob;
+    oob->len = strlen(prefix);
+    oob->prefix = prefix;
+    oob->cb = cb;
+    oob->next = _oobs;
+    _oobs = oob;
+}
+
+void ATParser::abort()
+{
+    _aborted = true;
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/ISM43362/ATParser/ATParser.h	Wed Oct 28 07:42:46 2020 +0000
@@ -0,0 +1,264 @@
+/* Copyright (c) 2015 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @section DESCRIPTION
+ *
+ * Parser for the AT command syntax
+ *
+ */
+#ifndef AT_PARSER_H
+#define AT_PARSER_H
+
+#include "mbed.h"
+#include <cstdarg>
+#include <vector>
+#include "BufferedSpi.h"
+#include "Callback.h"
+
+
+/**
+* Parser class for parsing AT commands
+*
+* Here are some examples:
+* @code
+* ATParser at = ATParser(serial, "\r\n");
+* int value;
+* char buffer[100];
+*
+* at.send("AT") && at.recv("OK");
+* at.send("AT+CWMODE=%d", 3) && at.recv("OK");
+* at.send("AT+CWMODE?") && at.recv("+CWMODE:%d\r\nOK", &value);
+* at.recv("+IPD,%d:", &value);
+* at.read(buffer, value);
+* at.recv("OK");
+* @endcode
+*/
+class ATParser
+{
+private:
+    // Serial information
+    BufferedSpi *_serial_spi;
+    int _buffer_size;
+    char *_buffer;
+    Mutex _bufferMutex;
+    volatile int _timeout;
+
+    // Parsing information
+    const char *_delimiter;
+    int _delim_size;
+    char _in_prev;
+    bool dbg_on;
+    volatile bool _aborted;
+
+    struct oob {
+        unsigned len;
+        const char *prefix;
+        mbed::Callback<void()> cb;
+        oob *next;
+    };
+    oob *_oobs;
+
+public:
+    /**
+    * Constructor
+    *
+    * @param serial spi interface to use for AT commands
+    * @param buffer_size size of internal buffer for transaction
+    * @param timeout timeout of the connection
+    * @param delimiter string of characters to use as line delimiters
+    */
+    ATParser(BufferedSpi &serial_spi, const char *delimiter = "\r\n", int buffer_size = 1440, int timeout = 8000, bool debug = false) :
+        _serial_spi(&serial_spi),
+        _buffer_size(buffer_size), _in_prev(0), _oobs(NULL)
+    {
+        _buffer = new char[buffer_size];
+        setTimeout(timeout);
+        setDelimiter(delimiter);
+        debugOn(debug);
+    }
+
+    /**
+    * Destructor
+    */
+    ~ATParser()
+    {
+        while (_oobs) {
+            struct oob *oob = _oobs;
+            _oobs = oob->next;
+            delete oob;
+        }
+        delete[] _buffer;
+    }
+
+    /**
+    * Allows timeout to be changed between commands
+    *
+    * @param timeout timeout of the connection
+    */
+    void setTimeout(int timeout) 
+    {
+        _timeout = timeout;
+        _serial_spi->setTimeout(timeout);
+    }
+
+    /**
+    * Sets string of characters to use as line delimiters
+    *
+    * @param delimiter string of characters to use as line delimiters
+    */
+    void setDelimiter(const char *delimiter) {
+        _delimiter = delimiter;
+        _delim_size = strlen(delimiter);
+    }
+    
+    /**
+    * Allows echo to be on or off
+    *
+    * @param echo 1 for echo and 0 turns it off
+    */
+    void debugOn(uint8_t on) {
+        dbg_on = (on) ? 1 : 0;
+    }
+
+    /**
+     * Sends an AT command
+     *
+     * Sends a formatted command using printf style formatting
+     * @see printf
+     *
+     * @param command printf-like format string of command to send which
+     *                is appended with a newline
+     * @param ... all printf-like arguments to insert into command
+     * @return true only if command is successfully sent
+     */
+    bool send(const char *command, ...);
+
+    bool vsend(const char *command, va_list args);
+
+    /**
+     * Receive an AT response
+     *
+     * Receives a formatted response using scanf style formatting
+     * @see scanf
+     *
+     * Responses are parsed line at a time.
+     * Any received data that does not match the response is ignored until
+     * a timeout occurs.
+     *
+     * @param response scanf-like format string of response to expect
+     * @param ... all scanf-like arguments to extract from response
+     * @return true only if response is successfully matched
+     */
+    bool recv(const char *response, ...);
+    bool vrecv(const char *response, va_list args);
+
+
+    /**
+     * Write a single byte to the underlying stream
+     *
+     * @param c The byte to write
+     * @return The byte that was written or -1 during a timeout
+     */
+    int putc(char c);
+
+    /**
+     * Get a single byte from the underlying stream
+     *
+     * @return The byte that was read or -1 during a timeout
+     */
+    int getc();
+
+    /**
+     * Write an array of bytes to the underlying stream
+     * assuming the header of the command is already in _txbuffer
+     *
+     * @param data the array of bytes to write
+     * @param size_of_data number of bytes in data array
+     * @param size_in_buff number of bytes already in the internal buff
+     * @return number of bytes written or -1 on failure
+     */
+    int write(const char *data, int size_of_data, int size_in_buff);
+
+    /**
+     * Read an array of bytes from the underlying stream
+     *
+     * @param data the destination for the read bytes
+     * @param size number of bytes to read
+     * @return number of bytes read or -1 on failure
+     */
+    int read(char *data);
+
+    /**
+     * Direct printf to underlying stream
+     * @see printf
+     *
+     * @param format format string to pass to printf
+     * @param ... arguments to printf
+     * @return number of bytes written or -1 on failure
+     */
+    int printf(const char *format, ...);
+    int vprintf(const char *format, va_list args);
+
+    /**
+    * Direct scanf on underlying stream
+    * @see ::scanf
+    *
+    * @param format format string to pass to scanf
+    * @param ... arguments to scanf
+    * @return number of bytes read or -1 on failure
+    */
+    int scanf(const char *format, ...);
+
+    int vscanf(const char *format, va_list args);
+
+    /**
+     * Attach a callback for out-of-band data
+     *
+     * @param prefix string on when to initiate callback
+     * @param func callback to call when string is read
+     * @note out-of-band data is only processed during a scanf call
+     */
+    void oob(const char *prefix, mbed::Callback<void()> func);
+
+    /**
+     * Flushes the underlying stream
+     */
+    void flush();
+
+    /**
+     * Abort current recv
+     *
+     * Can be called from oob handler to interrupt the current
+     * recv operation.
+     */
+    void abort();
+    
+    /**
+    * Process out-of-band data
+    *
+    * Process out-of-band data in the receive buffer. This function
+    * returns immediately if there is no data to process.
+    *
+    * @return true if oob data processed, false otherwise
+    */
+    bool process_oob(void);
+    /**
+    * Get buffer_size
+    */
+    int get_size(void) {
+        return _buffer_size;
+    }
+
+};
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/ISM43362/ATParser/BufferedSpi/Buffer/MyBuffer.cpp	Wed Oct 28 07:42:46 2020 +0000
@@ -0,0 +1,83 @@
+
+/**
+ * @file    Buffer.cpp
+ * @brief   Software Buffer - Templated Ring Buffer for most data types
+ * @author  sam grove
+ * @version 1.0
+ * @see     
+ *
+ * Copyright (c) 2013
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+#include "MyBuffer.h"
+
+template <class T>
+MyBuffer<T>::MyBuffer(uint32_t size)
+{
+    _buf = new T [size];
+    _size = size;
+    clear();
+    
+    return;
+}
+
+template <class T>
+MyBuffer<T>::~MyBuffer()
+{
+    delete [] _buf;
+    
+    return;
+}
+
+template <class T>
+uint32_t MyBuffer<T>::getSize() 
+{ 
+    return this->_size; 
+}
+
+template <class T>
+    uint32_t MyBuffer<T>::getNbAvailable()
+{
+    if ( _wloc >= _rloc) return (_wloc - _rloc);
+    else return (_size - _rloc + _wloc);
+}
+
+template <class T>
+void MyBuffer<T>::clear(void)
+{
+    _wloc = 0;
+    _rloc = 0;
+    memset(_buf, 0, _size);
+    
+    return;
+}
+
+template <class T>
+uint32_t MyBuffer<T>::peek(char c)
+{
+    return 1;
+}
+
+// make the linker aware of some possible types
+template class MyBuffer<uint8_t>;
+template class MyBuffer<int8_t>;
+template class MyBuffer<uint16_t>;
+template class MyBuffer<int16_t>;
+template class MyBuffer<uint32_t>;
+template class MyBuffer<int32_t>;
+template class MyBuffer<uint64_t>;
+template class MyBuffer<int64_t>;
+template class MyBuffer<char>;
+template class MyBuffer<wchar_t>;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/ISM43362/ATParser/BufferedSpi/Buffer/MyBuffer.h	Wed Oct 28 07:42:46 2020 +0000
@@ -0,0 +1,165 @@
+
+/**
+ * @file    Buffer.h
+ * @brief   Software Buffer - Templated Ring Buffer for most data types
+ * @author  sam grove
+ * @version 1.0
+ * @see     
+ *
+ * Copyright (c) 2013
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+#ifndef MYBUFFER_H
+#define MYBUFFER_H
+
+#include <stdint.h>
+#include <string.h>
+
+/** A templated software ring buffer
+ *
+ * Example:
+ * @code
+ *  #include "mbed.h"
+ *  #include "MyBuffer.h"
+ *
+ *  MyBuffer <char> buf;
+ *
+ *  int main()
+ *  {
+ *      buf = 'a';
+ *      buf.put('b');
+ *      char *head = buf.head();
+ *      puts(head);
+ *
+ *      char whats_in_there[2] = {0};
+ *      int pos = 0;
+ *
+ *      while(buf.available())
+ *      {   
+ *          whats_in_there[pos++] = buf;
+ *      }
+ *      printf("%c %c\n", whats_in_there[0], whats_in_there[1]);
+ *      buf.clear();
+ *      error("done\n\n\n");
+ *  }
+ * @endcode
+ */
+
+template <typename T>
+class MyBuffer
+{
+private:
+    T   *_buf;
+    volatile uint32_t   _wloc;
+    volatile uint32_t   _rloc;
+    uint32_t            _size;
+
+public:
+    /** Create a Buffer and allocate memory for it
+     *  @param size The size of the buffer
+     */
+    MyBuffer(uint32_t size = 0x100);
+    
+    /** Get the size of the ring buffer
+     * @return the size of the ring buffer
+     */
+     uint32_t getSize();
+     uint32_t getNbAvailable();
+    
+    /** Destry a Buffer and release it's allocated memory
+     */
+    ~MyBuffer();
+    
+    /** Add a data element into the buffer
+     *  @param data Something to add to the buffer
+     */
+    void put(T data);
+    
+    /** Remove a data element from the buffer
+     *  @return Pull the oldest element from the buffer
+     */
+    T get(void);
+    
+    /** Get the address to the head of the buffer
+     *  @return The address of element 0 in the buffer
+     */
+    T *head(void);
+    
+    /** Reset the buffer to 0. Useful if using head() to parse packeted data
+     */
+    void clear(void);
+    
+    /** Determine if anything is readable in the buffer
+     *  @return 1 if something can be read, 0 otherwise
+     */
+    uint32_t available(void);
+    
+    /** Overloaded operator for writing to the buffer
+     *  @param data Something to put in the buffer
+     *  @return
+     */
+    MyBuffer &operator= (T data)
+    {
+        put(data);
+        return *this;
+    }
+    
+    /** Overloaded operator for reading from the buffer
+     *  @return Pull the oldest element from the buffer 
+     */  
+    operator int(void)
+    {
+        return get();
+    }
+    
+     uint32_t peek(char c);
+    
+};
+
+template <class T>
+inline void MyBuffer<T>::put(T data)
+{
+    _buf[_wloc++] = data;
+    _wloc %= (_size-1);
+    
+    return;
+}
+
+template <class T>
+inline T MyBuffer<T>::get(void)
+{
+    T data_pos = _buf[_rloc++];
+    _rloc %= (_size-1);
+    
+    return data_pos;
+}
+
+template <class T>
+inline T *MyBuffer<T>::head(void)
+{
+    T *data_pos = &_buf[0];
+    
+    return data_pos;
+}
+
+template <class T>
+inline uint32_t MyBuffer<T>::available(void)
+{
+    return (_wloc == _rloc) ? 0 : 1;
+    //return 1;
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/ISM43362/ATParser/BufferedSpi/BufferedPrint.c	Wed Oct 28 07:42:46 2020 +0000
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "mbed_error.h"
+
+size_t BufferedSpiThunk(void *buf_serial, const void *s, size_t length);
+
+int BufferedPrintfC(void *stream, int size, const char* format, va_list arg)
+{
+    int r;
+    char buffer[512];
+    if (size >= 512) {
+        return -1;
+    }
+    memset(buffer, 0, size);
+    r = vsprintf(buffer, format, arg);
+    // this may not hit the heap but should alert the user anyways
+    if(r > (int32_t) size) {
+        error("%s %d buffer overwrite (max_buf_size: %d exceeded: %d)!\r\n", __FILE__, __LINE__, size, r);
+        return 0;
+    }
+    if ( r > 0 ) {
+        BufferedSpiThunk(stream, buffer, r);
+    }
+    return r;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/ISM43362/ATParser/BufferedSpi/BufferedSpi.cpp	Wed Oct 28 07:42:46 2020 +0000
@@ -0,0 +1,326 @@
+/**
+ * @file    BufferedSpi.cpp
+ * @brief   Software Buffer - Extends mbed SPI functionallity
+ * @author  Armelle Duboc
+ * @version 1.0
+ * @see
+ *
+ * Copyright (c) STMicroelectronics 2017
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "BufferedSpi.h"
+#include <stdarg.h>
+#include "mbed_debug.h"
+#include "mbed_error.h"
+
+// change to true to add few SPI debug lines
+#define local_debug false
+
+extern "C" int BufferedPrintfC(void *stream, int size, const char* format, va_list arg);
+
+void BufferedSpi::DatareadyRising(void)
+{
+   if (_cmddata_rdy_rising_event == 1) {
+     _cmddata_rdy_rising_event=0;
+   }
+}
+
+int BufferedSpi::wait_cmddata_rdy_high(void)
+{
+  Timer timer;
+  timer.start();
+
+  /* wait for dataready = 1 */
+  while(dataready.read() == 0) {
+       if (timer.read_ms() > _timeout) {
+          debug_if(local_debug,"ERROR: SPI write timeout\r\n");
+          return -1;
+       }
+  }
+
+  _cmddata_rdy_rising_event = 1;
+
+  return 0;
+}
+
+int BufferedSpi::wait_cmddata_rdy_rising_event(void)
+{
+    Timer timer;
+    timer.start();
+
+    while (_cmddata_rdy_rising_event == 1) {
+       if (timer.read_ms() > _timeout) {
+           _cmddata_rdy_rising_event = 0;
+           if (dataready.read() == 1) {
+               debug_if(local_debug,"ERROR: We missed rising event !! (timemout=%d)\r\n", _timeout);
+           }
+           debug_if(local_debug,"ERROR: SPI read timeout\r\n");
+           return -1;
+       }
+    }
+
+    return 0;
+}
+
+BufferedSpi::BufferedSpi(PinName mosi, PinName miso, PinName sclk, PinName _nss, PinName _datareadypin,
+                         uint32_t buf_size, uint32_t tx_multiple, const char* name)
+    : SPI(mosi, miso, sclk, NC), nss(_nss),  _txbuf((uint32_t)(tx_multiple*buf_size)), _rxbuf(buf_size), dataready(_datareadypin)
+{
+    this->_buf_size = buf_size;
+    this->_tx_multiple = tx_multiple;
+    this->_sigio_event = 0;
+
+    _datareadyInt = new InterruptIn(_datareadypin);
+    _datareadyInt->rise(callback(this, &BufferedSpi::DatareadyRising));
+
+    _cmddata_rdy_rising_event = 1;
+
+    return;
+}
+
+BufferedSpi::~BufferedSpi(void)
+{
+
+    return;
+}
+
+void BufferedSpi::frequency(int hz)
+{
+    SPI::frequency(hz);
+}
+
+void BufferedSpi::format(int bits, int mode)
+{
+    SPI::format(bits, mode);
+}
+
+void BufferedSpi::disable_nss()
+{
+    nss = 1;
+    wait_us(15);
+}
+
+void BufferedSpi::enable_nss()
+{
+    nss = 0;
+    wait_us(15);
+}
+
+int BufferedSpi::readable(void)
+{
+    return _rxbuf.available();  // note: look if things are in the buffer
+}
+
+int BufferedSpi::writeable(void)
+{
+    return 1;   // buffer allows overwriting by design, always true
+}
+
+int BufferedSpi::getc(void)
+{
+    if (_rxbuf.available())
+        return _rxbuf;
+    else return -1;
+}
+
+int BufferedSpi::putc(int c)
+{
+    _txbuf = (char)c;
+
+    return c;
+}
+
+void BufferedSpi::flush_txbuf(void)
+{
+    _txbuf.clear();
+}
+
+int BufferedSpi::puts(const char *s)
+{
+    if (s != NULL) {
+        const char* ptr = s;
+    
+        while(*(ptr) != 0) {
+            _txbuf = *(ptr++);
+        }
+        _txbuf = '\n';  // done per puts definition
+        BufferedSpi::txIrq();                // only write to hardware in one place
+        return (ptr - s) + 1;
+    }
+    return 0;
+}
+
+extern "C" size_t BufferedSpiThunk(void *buf_spi, const void *s, size_t length)
+{
+    BufferedSpi *buffered_spi = (BufferedSpi *)buf_spi;
+    return buffered_spi->buffwrite(s, length);
+}
+
+int BufferedSpi::printf(const char* format, ...)
+{
+    va_list arg;
+    va_start(arg, format);
+    int r = BufferedPrintfC((void*)this, this->_buf_size, format, arg);
+    va_end(arg);
+    return r;
+}
+
+ssize_t BufferedSpi::buffwrite(const void *s, size_t length)
+{
+    /* flush buffer from previous message */
+    this->flush_txbuf();
+
+    if (wait_cmddata_rdy_high() < 0) {
+        debug_if(local_debug, "BufferedSpi::buffwrite timeout (%d)\r\n", _timeout);
+        return -1;
+    }
+
+    this->enable_nss();
+    
+    if (s != NULL && length > 0) {
+        /* 1st fill _txbuf */
+        const char* ptr = (const char*)s;
+        const char* end = ptr + length;
+    
+        while (ptr != end) {
+            _txbuf = *(ptr++);
+        }
+        if (length&1) { /* padding to send the last char */
+            _txbuf = '\n';
+            length++;
+        }
+
+        /* 2nd write in SPI */
+        BufferedSpi::txIrq();                // only write to hardware in one place
+
+        this->disable_nss();
+        return ptr - (const char*)s;
+    }
+    this->disable_nss();
+
+    return 0;
+}
+
+ssize_t BufferedSpi::buffsend(size_t length)
+{
+    /* wait for dataready = 1 */
+    if (wait_cmddata_rdy_high() < 0) {
+        debug_if(local_debug, "BufferedSpi::buffsend timeout (%d)\r\n", _timeout);
+        return -1;
+    }
+
+    this->enable_nss();
+
+    /* _txbuffer is already filled with data to send */
+    /* check if _txbuffer needs padding to send the last char */
+    if (length & 1) {
+        _txbuf = '\n';
+        length++;
+    }
+    BufferedSpi::txIrq();                // only write to hardware in one place
+
+    this->disable_nss();
+
+    return length;
+}
+
+ssize_t BufferedSpi::read()
+{
+    return this->read(0);
+}
+
+ssize_t BufferedSpi::read(uint32_t max)
+{
+    uint32_t len = 0;
+    int tmp;
+
+    disable_nss();
+
+    /* wait for data ready is up */
+    if(wait_cmddata_rdy_rising_event() != 0) {
+        debug_if(local_debug, "BufferedSpi::read timeout (%d)\r\n", _timeout);
+        return -1;
+    }
+
+    enable_nss();
+    while (dataready.read() == 1 && (len < (_buf_size - 1))) {
+        tmp = SPI::write(0xAA);  // dummy write to receive 2 bytes
+
+        if (!((len == 0) && (tmp == 0x0A0D))) {
+            /* do not take into account the 2 firts \r \n char in the buffer */
+            if ((max == 0) || (len < max)) {
+                _rxbuf = (char)(tmp & 0x00FF);
+                _rxbuf = (char)((tmp >>8)& 0xFF);
+                len += 2;
+            }
+        }
+    }
+    disable_nss();
+
+    if (len >= _buf_size) {
+        debug_if(local_debug, "firmware ERROR ES_WIFI_ERROR_STUFFING_FOREVER\r\n");
+        return -1;
+    }
+
+    debug_if(local_debug, "SPI READ %d BYTES\r\n", len);
+
+    return len;
+}
+
+void BufferedSpi::txIrq(void)
+{ /* write everything available in the _txbuffer */
+    int value = 0;
+    int dbg_cnt = 0;
+    while (_txbuf.available() && (_txbuf.getNbAvailable()>0)) {
+        value = _txbuf.get();
+        if (_txbuf.available() && ((_txbuf.getNbAvailable()%2)!=0)) {
+            value |= ((_txbuf.get()<<8)&0XFF00);
+            SPI::write(value);
+            dbg_cnt++;
+        }
+    }
+    debug_if(local_debug, "SPI Sent %d BYTES\r\n", 2*dbg_cnt);
+    // disable the TX interrupt when there is nothing left to send
+    BufferedSpi::attach(NULL, BufferedSpi::TxIrq);
+    // trigger callback if necessary
+    if (_cbs[TxIrq]) {
+        _cbs[TxIrq]();
+    }
+    return;
+}
+
+void BufferedSpi::prime(void)
+{
+    BufferedSpi::txIrq();                // only write to hardware in one place
+    return;
+}
+
+void BufferedSpi::attach(Callback<void()> func, IrqType type)
+{
+    _cbs[type] = func;
+}
+
+void BufferedSpi::sigio(Callback<void()> func) {
+    core_util_critical_section_enter();
+    _sigio_cb = func;
+    if (_sigio_cb) {
+        if (_sigio_event == 1) {
+            _sigio_cb();
+            _sigio_event = 0;
+        }
+    }
+    core_util_critical_section_exit();
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/ISM43362/ATParser/BufferedSpi/BufferedSpi.h	Wed Oct 28 07:42:46 2020 +0000
@@ -0,0 +1,235 @@
+
+/**
+ * @file    BufferedSpi.h
+ * @brief   Software Buffer - Extends mbed SPI functionallity
+ * @author  Armelle Duboc
+ * @version 1.0
+ * @see
+ *
+ * Copyright (c) STMicroelectronics 2017
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BUFFEREDSPI_H
+#define BUFFEREDSPI_H
+ 
+#include "mbed.h"
+#include "MyBuffer.h"
+
+/** A spi port (SPI) for communication with wifi device
+ *
+ * Can be used for Full Duplex communication, or Simplex by specifying
+ * one pin as NC (Not Connected)
+ *
+ * Example:
+ * @code
+ *  #include "mbed.h"
+ *  #include "BufferedSerial.h"
+ *
+ *  BufferedSerial pc(USBTX, USBRX);
+ *
+ *  int main()
+ *  { 
+ *      while(1)
+ *      {
+ *          Timer s;
+ *        
+ *          s.start();
+ *          pc.printf("Hello World - buffered\n");
+ *          int buffered_time = s.read_us();
+ *          wait(0.1f); // give time for the buffer to empty
+ *        
+ *          s.reset();
+ *          printf("Hello World - blocking\n");
+ *          int polled_time = s.read_us();
+ *          s.stop();
+ *          wait(0.1f); // give time for the buffer to empty
+ *        
+ *          pc.printf("printf buffered took %d us\n", buffered_time);
+ *          pc.printf("printf blocking took %d us\n", polled_time);
+ *          wait(0.5f);
+ *      }
+ *  }
+ * @endcode
+ */
+
+/**
+ *  @class BufferedSpi
+ *  @brief Software buffers and interrupt driven tx and rx for Serial
+ */  
+class BufferedSpi : public SPI 
+{
+private:
+    DigitalOut    nss;
+    MyBuffer <char> _txbuf;
+    uint32_t      _buf_size;
+    uint32_t      _tx_multiple;
+    volatile int _timeout;
+    void txIrq(void);
+    void prime(void);
+
+    InterruptIn* _datareadyInt;
+    volatile int _cmddata_rdy_rising_event;
+    void DatareadyRising(void);
+    int wait_cmddata_rdy_rising_event(void);
+    int wait_cmddata_rdy_high(void);
+
+
+    Callback<void()> _cbs[2];
+
+    Callback<void()> _sigio_cb;
+    uint8_t          _sigio_event;
+
+public:
+    MyBuffer <char> _rxbuf;
+    DigitalIn dataready;
+    enum IrqType {
+        RxIrq = 0,
+        TxIrq,
+
+        IrqCnt
+    };
+
+    /** Create a BufferedSpi Port, connected to the specified transmit and receive pins
+     *  @param SPI mosi pin
+     *  @param SPI miso pin
+     *  @param SPI sclk pin
+     *  @param SPI nss pin
+     *  @param Dataready pin
+     *  @param buf_size printf() buffer size
+     *  @param tx_multiple amount of max printf() present in the internal ring buffer at one time
+     *  @param name optional name
+    */
+    BufferedSpi(PinName mosi, PinName miso, PinName sclk, PinName nss, PinName datareadypin, uint32_t buf_size = 1480, uint32_t tx_multiple = 4,const char* name=NULL);
+    
+    /** Destroy a BufferedSpi Port
+     */
+    virtual ~BufferedSpi(void);
+    
+    /** call to SPI frequency Function
+     */
+    virtual void frequency(int hz);
+    
+    /** clear the transmit buffer
+     */
+    virtual void flush_txbuf(void);
+    
+    /** call to SPI format function 
+     */
+    virtual void format(int bits, int mode);
+    
+    virtual void enable_nss(void);
+    
+    virtual void disable_nss(void);
+    
+    /** Check on how many bytes are in the rx buffer
+     *  @return 1 if something exists, 0 otherwise
+     */
+    virtual int readable(void);
+    
+    /** Check to see if the tx buffer has room
+     *  @return 1 always has room and can overwrite previous content if too small / slow
+     */
+    virtual int writeable(void);
+    
+    /** Get a single byte from the BufferedSpi Port.
+     *  Should check readable() before calling this.
+     *  @return A byte that came in on the SPI Port
+     */
+    virtual int getc(void);
+    
+    /** Write a single byte to the BufferedSpi Port.
+     *  @param c The byte to write to the SPI Port
+     *  @return The byte that was written to the SPI Port Buffer
+     */
+    virtual int putc(int c);
+    
+    /** Write a string to the BufferedSpi Port. Must be NULL terminated
+     *  @param s The string to write to the Spi Port
+     *  @return The number of bytes written to the Spi Port Buffer
+     */
+    virtual int puts(const char *s);
+    
+    /** Write a formatted string to the BufferedSpi Port.
+     *  @param format The string + format specifiers to write to the Spi Port
+     *  @return The number of bytes written to the Spi Port Buffer
+     */
+    virtual int printf(const char* format, ...);
+    
+    /** Write data to the Buffered Spi Port
+     *  @param s A pointer to data to send
+     *  @param length The amount of data being pointed to
+     *  @return The number of bytes written to the Spi Port Buffer
+     */
+    virtual ssize_t buffwrite(const void *s, std::size_t length);
+
+    /** Send datas to the Spi port that are already present
+     *  in the internal _txbuffer
+     *  @param length
+     *  @return the number of bytes written on the SPI port
+     */
+    virtual ssize_t buffsend(size_t length);
+
+    /** Read data from the Spi Port to the _rxbuf
+     *  @param max: optional. = max sieze of the input read
+     *  @return The number of bytes read from the SPI port and written to the _rxbuf
+     */
+    virtual ssize_t read();
+    virtual ssize_t read(uint32_t max);
+
+    /**
+    * Allows timeout to be changed between commands
+    *
+    * @param timeout timeout of the connection
+    */
+    void setTimeout(int timeout)
+    {
+        /*  this is a safe guard timeout in case module is stuck
+         *  so take 5 sec margin compared to module timeout, to
+         *  really only detect case where module is stuck */
+        _timeout = timeout + 5000;
+    }
+
+    /** Register a callback once any data is ready for sockets
+     *  @param func     Function to call on state change
+     */
+    virtual void sigio(Callback<void()> func);
+    
+    /** Attach a function to call whenever a serial interrupt is generated
+     *  @param func A pointer to a void function, or 0 to set as none
+     *  @param type Which serial interrupt to attach the member function to (Serial::RxIrq for receive, TxIrq for transmit buffer empty)
+     */
+     virtual void attach(Callback<void()> func, IrqType type=RxIrq);
+     
+    /** Attach a member function to call whenever a serial interrupt is generated
+     *  @param obj pointer to the object to call the member function on
+     *  @param method pointer to the member function to call
+     *  @param type Which serial interrupt to attach the member function to (Serial::RxIrq for receive, TxIrq for transmit buffer empty)
+     */
+    template <typename T>
+    void attach(T *obj, void (T::*method)(), IrqType type=RxIrq) {
+        attach(Callback<void()>(obj, method), type);
+    }
+
+    /** Attach a member function to call whenever a serial interrupt is generated
+     *  @param obj pointer to the object to call the member function on
+     *  @param method pointer to the member function to call
+     *  @param type Which serial interrupt to attach the member function to (Serial::RxIrq for receive, TxIrq for transmit buffer empty)
+     */
+    template <typename T>
+    void attach(T *obj, void (*method)(T*), IrqType type=RxIrq) {
+        attach(Callback<void()>(obj, method), type);
+    }
+};
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/ISM43362/ISM43362.cpp	Wed Oct 28 07:42:46 2020 +0000
@@ -0,0 +1,647 @@
+/* ISM43362 Example
+*
+* Copyright (c) STMicroelectronics 2017
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <string.h>
+#include "ISM43362.h"
+#include "mbed_debug.h"
+
+// ao activate  / de-activate debug
+#define ism_debug false
+
+ISM43362::ISM43362(PinName mosi, PinName miso, PinName sclk, PinName nss, PinName resetpin, PinName datareadypin, PinName wakeup, bool debug)
+    : _bufferspi(mosi, miso, sclk, nss, datareadypin), _parser(_bufferspi), _resetpin(resetpin),
+      _packets(0), _packets_end(&_packets)
+{
+    DigitalOut wakeup_pin(wakeup);
+    ISM43362::setTimeout((uint32_t)5000);
+    _bufferspi.format(16, 0); /* 16bits, ploarity low, phase 1Edge, master mode */
+    _bufferspi.frequency(20000000); /* up to 20 MHz */
+    _active_id = 0xFF;
+
+    reset();
+
+    _parser.debugOn(debug);
+}
+
+/**
+  * @brief  Parses and returns number from string.
+  * @param  ptr: pointer to string
+  * @param  cnt: pointer to the number of parsed digit
+  * @retval integer value.
+  */
+#define CHARISHEXNUM(x)                 (((x) >= '0' && (x) <= '9') || \
+                                         ((x) >= 'a' && (x) <= 'f') || \
+                                         ((x) >= 'A' && (x) <= 'F'))
+#define CHARISNUM(x)                    ((x) >= '0' && (x) <= '9')
+#define CHAR2NUM(x)                     ((x) - '0')
+
+
+extern "C" int32_t ParseNumber(char* ptr, uint8_t* cnt) 
+{
+    uint8_t minus = 0, i = 0;
+    int32_t sum = 0;
+    
+    if (*ptr == '-') {                                		/* Check for minus character */
+        minus = 1;
+        ptr++;
+        i++;
+    }
+    while (CHARISNUM(*ptr) || (*ptr=='.')) {   /* Parse number */
+        if (*ptr == '.') {
+            ptr++; // next char
+        } else {
+            sum = 10 * sum + CHAR2NUM(*ptr);
+            ptr++;
+            i++;
+        }
+    }
+
+    if (cnt != NULL) {                   /* Save number of characters used for number */
+        *cnt = i;
+    }
+    if (minus) {                         /* Minus detected */
+        return 0 - sum;
+    }
+    return sum;                          /* Return number */
+}
+
+const char *ISM43362::get_firmware_version(void)
+{
+    char tmp_buffer[250];
+    char *ptr, *ptr2;
+
+    if(!(_parser.send("I?") && _parser.recv("%s\r\n", tmp_buffer) && check_response())) {
+        debug_if(ism_debug, "get_firmware_version is FAIL\r\n");
+        return 0;
+    }
+
+    // Get the first version in the string
+    ptr = strtok((char *)tmp_buffer, ",");
+    ptr = strtok(NULL, ",");
+    ptr2 = strtok(NULL, ",");
+    if (ptr == NULL) {
+        debug_if(ism_debug, "get_firmware_version decoding is FAIL\r\n");
+        return 0;
+    }
+    strncpy(_fw_version, ptr , ptr2-ptr);
+
+    debug_if(ism_debug, "get_firmware_version = [%s]\r\n", _fw_version);
+
+    return _fw_version;
+}
+
+bool ISM43362::reset(void)
+{
+    debug_if(ism_debug,"Reset Module\r\n");
+    _resetpin = 0;
+    wait_ms(10);
+    _resetpin = 1;
+    wait_ms(500);
+
+    /*  Wait for prompt line */
+    if (!_parser.recv("> \r\n")) {
+        debug_if(ism_debug,"Reset Module failed\r\n");
+        return false;
+    }
+
+    return true;
+}
+
+void ISM43362::print_rx_buff(void) {
+    char tmp[150] = {0};
+    uint16_t i = 0;
+    while(i  < 150) {
+        int c = _parser.getc();
+        if (c < 0)
+            break;
+        tmp[i] = c;
+        debug_if(ism_debug," 0x%2X",c);
+        i++;
+    }
+    debug_if(ism_debug,"Buffer content =====%s=====\r\n",tmp);
+}
+
+/*  checks the standard OK response of the WIFI module, shouldbe:
+ *  \r\nDATA\r\nOK\r\n>sp
+ *  or
+ *  \r\nERROR\r\nUSAGE\r\n>sp
+ *  function returns true if OK, false otherwise. In case of error,
+ *  print error content then flush buffer */
+bool ISM43362::check_response(void)
+{
+    if(!_parser.recv("OK\r\n")) {
+        print_rx_buff();
+        _parser.flush();
+        return false;
+    }
+
+    /*  Then we should get "> ", but sometimes it seems it's missing,
+     *  let's make it optional */
+    if(!_parser.recv("> \r\n")) {
+        debug_if(ism_debug, "Missing prompt in WIFI resp\r\n");
+        print_rx_buff();
+        _parser.flush();
+        return false;
+    }
+
+    /*  Inventek module do stuffing / padding of data with 0x15,
+     *  in case buffer containes such */
+    while(1) {
+        int c = _parser.getc();
+        if ( c == 0x15) {
+            continue;
+        } else {
+            /*  How to put it back if needed ? */
+            break;
+        }
+    }
+
+    return true;
+}
+
+bool ISM43362::dhcp(bool enabled)
+{
+    return (_parser.send("C4=%d", enabled ? 1:0) && check_response());
+}
+
+bool ISM43362::connect(const char *ap, const char *passPhrase)
+{
+    if (!(_parser.send("C1=%s", ap) && check_response())) {
+        return false;
+    }
+
+    if (!(_parser.send("C2=%s", passPhrase) && check_response())) {
+        return false;
+    }
+    /* TODO security level = 3 , is it hardcoded or not ???? */
+    if (!(_parser.send("C3=3") && check_response())) {
+        return false;
+    }
+    /* now connect */
+    /* connect response contains more data that we don't need now,
+     * So we only look for OK, the flush the end of it */
+    if (!(_parser.send("C0") && check_response())) {
+        return false;
+    }
+
+    return true;
+}
+
+bool ISM43362::disconnect(void)
+{
+    return (_parser.send("CD") && check_response());
+}
+
+const char *ISM43362::getIPAddress(void)
+{
+    char tmp_ip_buffer[250];
+    char *ptr, *ptr2;
+
+    if(!(_parser.send("C?")
+                && _parser.recv("%s\r\n", tmp_ip_buffer) && check_response())) {
+        debug_if(ism_debug,"getIPAddress LINE KO: %s", tmp_ip_buffer);
+        return 0;
+    }
+
+    /* Get the IP address in the result */
+    /* TODO : check if the begining of the string is always = "eS-WiFi_AP_C47F51011231," */
+    ptr = strtok((char *)tmp_ip_buffer, ",");
+    ptr = strtok(NULL, ",");
+    ptr = strtok(NULL, ",");
+    ptr = strtok(NULL, ",");
+    ptr = strtok(NULL, ",");
+    ptr = strtok(NULL, ",");
+    ptr2 = strtok(NULL, ",");
+    if (ptr == NULL) return 0;
+    strncpy(_ip_buffer, ptr , ptr2-ptr);
+
+    tmp_ip_buffer[59] = 0;
+    debug_if(ism_debug,"receivedIPAddress: %s\n", _ip_buffer);
+
+    return _ip_buffer;
+}
+
+const char *ISM43362::getMACAddress(void)
+{
+    if(!(_parser.send("Z5") && _parser.recv("%s\r\n", _mac_buffer) && check_response())) {
+        debug_if(ism_debug,"receivedMacAddress LINE KO: %s", _mac_buffer);
+        return 0;
+    }
+
+    debug_if(ism_debug,"receivedMacAddress:%s, size=%d\r\n", _mac_buffer, sizeof(_mac_buffer));
+
+    return _mac_buffer;
+}
+
+const char *ISM43362::getGateway()
+{
+    char tmp[250];
+
+    if(!(_parser.send("C?") && _parser.recv("%s\r\n", tmp) && check_response())) {
+        debug_if(ism_debug,"getGateway LINE KO: %s\r\n", tmp);
+        return 0;
+    }
+
+    /* Extract the Gateway in the received buffer */
+    char *ptr;
+    ptr = strtok(tmp,",");
+    for (int i = 0; i< 7;i++) {
+        if (ptr == NULL) break;
+         ptr = strtok(NULL,",");
+    }
+
+    strncpy(_gateway_buffer, ptr, sizeof(_gateway_buffer));
+
+    debug_if(ism_debug,"getGateway: %s\r\n", _gateway_buffer);
+
+    return _gateway_buffer;
+}
+
+const char *ISM43362::getNetmask()
+{
+    char tmp[250];
+
+    if(!(_parser.send("C?") && _parser.recv("%s\r\n", tmp) && check_response())) {
+        debug_if(ism_debug,"getNetmask LINE KO: %s", tmp);
+        return 0;
+    }
+
+    /* Extract Netmask in the received buffer */
+    char *ptr;
+    ptr = strtok(tmp,",");
+    for (int i = 0; i< 6;i++) {
+        if (ptr == NULL) break;
+         ptr = strtok(NULL,",");
+    }
+
+    strncpy(_netmask_buffer, ptr, sizeof(_netmask_buffer));
+
+    debug_if(ism_debug,"getNetmask: %s\r\n", _netmask_buffer);
+
+    return _netmask_buffer;
+}
+
+int8_t ISM43362::getRSSI()
+{
+    int8_t rssi;
+    char tmp[25];
+
+    if(!(_parser.send("CR") && _parser.recv("%s\r\n", tmp) && check_response())) {
+        debug_if(ism_debug,"getRSSI LINE KO: %s\r\n", tmp);
+        return 0;
+    }
+
+    rssi = ParseNumber(tmp, NULL);
+
+    debug_if(ism_debug,"getRSSI: %d\r\n", rssi);
+
+    return rssi;
+}
+/**
+  * @brief  Parses Security type.
+  * @param  ptr: pointer to string
+  * @retval Encryption type.
+  */
+extern "C" nsapi_security_t ParseSecurity(char* ptr) 
+{
+  if(strstr(ptr,"Open")) return NSAPI_SECURITY_NONE;
+  else if(strstr(ptr,"WEP")) return NSAPI_SECURITY_WEP;
+  else if(strstr(ptr,"WPA")) return NSAPI_SECURITY_WPA;   
+  else if(strstr(ptr,"WPA2 AES")) return NSAPI_SECURITY_WPA2; 
+  else if(strstr(ptr,"WPA WPA2")) return NSAPI_SECURITY_WPA_WPA2; 
+  else if(strstr(ptr,"WPA2 TKIP")) return NSAPI_SECURITY_UNKNOWN; // ?? no match in mbed ?   
+  else return NSAPI_SECURITY_UNKNOWN;           
+}
+
+/**
+  * @brief  Convert char in Hex format to integer.
+  * @param  a: character to convert
+  * @retval integer value.
+  */
+extern "C"  uint8_t Hex2Num(char a) 
+{
+    if (a >= '0' && a <= '9') {                             /* Char is num */
+        return a - '0';
+    } else if (a >= 'a' && a <= 'f') {                      /* Char is lowercase character A - Z (hex) */
+        return (a - 'a') + 10;
+    } else if (a >= 'A' && a <= 'F') {                      /* Char is uppercase character A - Z (hex) */
+        return (a - 'A') + 10;
+    }
+    
+    return 0;
+}
+
+/**
+  * @brief  Extract a hex number from a string.
+  * @param  ptr: pointer to string
+  * @param  cnt: pointer to the number of parsed digit
+  * @retval Hex value.
+  */
+extern "C" uint32_t ParseHexNumber(char* ptr, uint8_t* cnt) 
+{
+    uint32_t sum = 0;
+    uint8_t i = 0;
+    
+    while (CHARISHEXNUM(*ptr)) {         /* Parse number */
+        sum <<= 4;
+        sum += Hex2Num(*ptr);
+        ptr++;
+        i++;
+    }
+    
+    if (cnt != NULL) {                  /* Save number of characters used for number */
+        *cnt = i;
+    }
+    return sum;                         /* Return number */
+}
+
+bool ISM43362::isConnected(void)
+{
+    return getIPAddress() != 0;
+}
+
+int ISM43362::scan(WiFiAccessPoint *res, unsigned limit)
+{
+    unsigned cnt = 0, num=0;
+    nsapi_wifi_ap_t ap;
+    char *ptr;
+    char tmp[256];
+
+    if(!(_parser.send("F0"))) {
+        debug_if(ism_debug,"scan error\r\n");
+        return 0;
+    }
+
+    /* Parse the received buffer and fill AP buffer */
+    while (_parser.recv("#%s\n", tmp)) {
+        debug_if(ism_debug,"received:%s", tmp);
+        ptr = strtok(tmp, ",");
+        num = 0;
+        while (ptr != NULL) {
+            if (limit != 0 && cnt >= limit) {
+                /* reached end */
+                break;
+            }
+            switch (num++) {
+            case 0: /* Ignore index */
+            case 4: /* Ignore Max Rate */
+            case 5: /* Ignore Network Type */
+            case 7: /* Ignore Radio Band */
+                break;
+            case 1:
+                ptr[strlen(ptr) - 1] = 0;
+                strncpy((char *)ap.ssid,  ptr+ 1, 32);
+                break;
+            case 2:
+                for (int i=0; i<6; i++) {
+                    ap.bssid[i] = ParseHexNumber(ptr + (i*3), NULL);
+                }
+                break;
+            case 3:
+                ap.rssi = ParseNumber(ptr, NULL);
+                break;
+            case 6:
+                ap.security = ParseSecurity(ptr);
+                break;
+            case 8:
+                ap.channel = ParseNumber(ptr, NULL);
+                res[cnt] = WiFiAccessPoint(ap);
+                cnt++;
+                num = 1;
+                break;
+            default:
+                break;
+            }
+            ptr = strtok(NULL, ",");
+        }
+    }
+
+    /* We may stop before having read all the APs list, so flush the rest of
+     * it as well as OK commands */
+    _parser.flush();
+
+    debug_if(ism_debug, "End of Scan: cnt=%d\n", cnt);
+
+    return cnt;
+
+}
+
+bool ISM43362::open(const char *type, int id, const char* addr, int port)
+{ /* TODO : This is the implementation for the client socket, need to check if need to create openserver too */
+    //IDs only 0-3
+    if((id < 0) ||(id > 3)) {
+        debug_if(ism_debug, "open: wrong id\n");
+        return false;
+    }
+    /* Set communication socket */
+    debug_if(ism_debug, "OPEN socket\n");
+    _active_id = id;
+    if (!(_parser.send("P0=%d", id) && check_response())) {
+        return false;
+    }
+    /* Set protocol */
+    if (!(_parser.send("P1=%s", type) && check_response())) {
+        return false;
+    }
+    /* Set address */
+    if (!(_parser.send("P3=%s", addr) && check_response())) {
+        return false;
+    }
+    if (!(_parser.send("P4=%d", port) && check_response())) {
+        return false;
+    }
+    /* Start client */
+    if (!(_parser.send("P6=1") && check_response())) {
+        return false;
+    }
+
+    /* request as much data as possible - i.e. module max size */
+    if (!(_parser.send("R1=%d", ES_WIFI_MAX_RX_PACKET_SIZE)&& check_response())) {
+            return -1;
+    }
+
+    return true;
+}
+
+bool ISM43362::dns_lookup(const char* name, char* ip)
+{
+    char tmp[30];
+
+    if (!(_parser.send("D0=%s", name) && _parser.recv("%s\r\n", tmp)
+                && check_response())) {
+        debug_if(ism_debug,"dns_lookup LINE KO: %s", tmp);
+        return 0;
+    }
+
+    strncpy(ip, tmp, sizeof(tmp));
+
+    debug_if(ism_debug, "ip of DNSlookup: %s\n", ip);
+    return 1;
+}
+
+bool ISM43362::send(int id, const void *data, uint32_t amount)
+{
+    // The Size limit has to be checked on caller side.
+    if (amount > ES_WIFI_MAX_RX_PACKET_SIZE) {
+        return false;
+    }
+
+    /* Activate the socket id in the wifi module */
+    if ((id < 0) ||(id > 3)) {
+        return false;
+    }
+    debug_if(ism_debug, "SEND socket amount %d\n", amount);
+    if (_active_id != id) {
+        _active_id = id;
+        if (!(_parser.send("P0=%d",id) && check_response())) {
+            return false;
+        }
+    }
+
+    /* Change the write timeout */
+    if (!(_parser.send("S2=%d", _timeout) && check_response())) {
+        return false;
+    }
+    /* set Write Transport Packet Size */
+    int i = _parser.printf("S3=%d\r", (int)amount);
+    if (i < 0) {
+        return false;
+    }
+    i = _parser.write((const char *)data, amount, i);
+    if (i < 0) {
+        return false;
+    }
+
+    if (!check_response()) {
+        return false;
+    }
+
+    return true;
+}
+
+int ISM43362::check_recv_status(int id, void *data)
+{
+    int read_amount;
+    static int keep_to = 0;
+
+    debug_if(ism_debug, "ISM43362 req check_recv_status\r\n");
+    /* Activate the socket id in the wifi module */
+    if ((id < 0) ||(id > 3)) {
+        return -1;
+    }
+
+    if (_active_id != id) {
+        _active_id = id;
+        if (!(_parser.send("P0=%d",id) && check_response())) {
+            return -1;
+        }
+    }
+
+
+    /* MBED wifi driver is meant to be non-blocking, but we need anyway to
+     * wait for some data on the RECV side to avoid overflow on TX side, the
+     * tiemout is defined in higher layer */
+    if (keep_to != _timeout) {
+        if (!(_parser.send("R2=%d", _timeout) && check_response())) {
+            return -1;
+        }
+        keep_to = _timeout;
+    }
+
+    if (!_parser.send("R0")) {
+        return -1;
+    }
+    read_amount = _parser.read((char *)data);
+
+    if(read_amount < 0) {
+        debug_if(ism_debug, "ERROR in data RECV, timeout?\r\n");
+        return -1; /* nothing to read */
+    }
+
+    /*  If there are spurious 0x15 at the end of the data, this is an error
+     *  we hall can get rid off of them :-(
+     *  This should not happen, but let's try to clean-up anyway
+     */
+    char *cleanup = (char *) data;
+    while ((read_amount > 0) && (cleanup[read_amount-1] == 0x15)) {
+        debug_if(ism_debug, "ISM4336 spurious 0X15 trashed\r\n");
+        /* Remove the trailling char then search again */
+        read_amount--;
+    }
+
+    if ((read_amount >= 6) && (strncmp("OK\r\n> ", (char *)data, 6) == 0)) {
+        debug_if(ism_debug, "ISM4336 recv 2 nothing to read=%d\r\n", read_amount);
+        return 0; /* nothing to read */
+    } else if ((read_amount >= 8) && (strncmp((char *)((uint32_t) data + read_amount - 8), "\r\nOK\r\n> ", 8)) == 0) {
+        /* bypass ""\r\nOK\r\n> " if present at the end of the chain */
+        read_amount -= 8;
+    } else {
+        debug_if(ism_debug, "ERROR in data RECV?, flushing %d bytes\r\n", read_amount);
+        int i = 0;
+        for (i = 0; i < read_amount; i++) {
+             debug_if(ism_debug, "%2X ", cleanup[i]);
+        }
+        cleanup[i] = 0;
+        debug_if(ism_debug, "\r\n%s\r\n", cleanup);
+        return -1; /* nothing to read */
+    }
+
+    debug_if(ism_debug, "ISM43362 read_amount=%d\r\n", read_amount);
+    return read_amount;
+}
+
+bool ISM43362::close(int id)
+{
+    if ((id <0) || (id > 3)) {
+        debug_if(ism_debug,"Wrong socket number\n");
+        return false;
+    }
+    /* Set connection on this socket */
+    debug_if(ism_debug,"CLOSE socket id=%d\n", id);
+    _active_id = id;
+    if (!(_parser.send("P0=%d", id) && check_response())) {
+        return false;
+    }
+    /* close this socket */
+    if (!(_parser.send("P6=0") && check_response())) {
+        return false;
+    }
+    return true;
+}
+
+void ISM43362::setTimeout(uint32_t timeout_ms)
+{
+    _timeout = timeout_ms;
+    _parser.setTimeout(timeout_ms);
+}
+
+bool ISM43362::readable()
+{
+  /* not applicable with SPI api */
+    return true;
+}
+
+bool ISM43362::writeable()
+{
+    /* not applicable with SPI api */
+    return true;
+}
+
+void ISM43362::attach(Callback<void()> func)
+{
+    /* not applicable with SPI api */
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/ISM43362/ISM43362.h	Wed Oct 28 07:42:46 2020 +0000
@@ -0,0 +1,246 @@
+/* ISM43362Interface Example
+ * Copyright (c) STMicroelectronics 2017
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ISM43362_H
+#define ISM43362_H
+#include "ATParser.h"
+
+#define ES_WIFI_MAX_SSID_NAME_SIZE                  32
+#define ES_WIFI_MAX_PSWD_NAME_SIZE                  32
+#define ES_WIFI_PRODUCT_ID_SIZE                     32
+#define ES_WIFI_PRODUCT_NAME_SIZE                   32
+#define ES_WIFI_FW_REV_SIZE                         16
+#define ES_WIFI_API_REV_SIZE                        16
+#define ES_WIFI_STACK_REV_SIZE                      16
+#define ES_WIFI_RTOS_REV_SIZE                       16
+
+// The input range for AT Command 'R1' is 0 to 1200 bytes
+// ‘R1’ Set Read Transport Packet Size (bytes)
+#define ES_WIFI_MAX_RX_PACKET_SIZE                     1200
+// Module maxume DATA payload for Tx packet is 1460
+#define ES_WIFI_MAX_TX_PACKET_SIZE                     1460
+
+/** ISM43362Interface class.
+    This is an interface to a ISM43362 radio.
+ */
+class ISM43362
+{
+public:
+    ISM43362(PinName mosi, PinName miso, PinName clk, PinName nss, PinName resetpin, PinName datareadypin, PinName wakeup, bool debug=false);
+    
+    /**
+    * Check firmware version of ISM43362
+    *
+    * @return null-terminated fw version or null if no version is read
+    */
+    const char *get_firmware_version(void);
+    
+    /**
+    * Reset ISM43362
+    *
+    * @return true only if ISM43362 resets successfully
+    */
+    bool reset(void);
+
+    /**
+    * Enable/Disable DHCP
+    *
+    * @param enabled DHCP enabled when true
+    * @return true only if ISM43362 enables/disables DHCP successfully
+    */
+    bool dhcp(bool enabled);
+
+    /**
+    * Connect ISM43362 to AP
+    *
+    * @param ap the name of the AP
+    * @param passPhrase the password of AP
+    * @return true only if ISM43362 is connected successfully
+    */
+    bool connect(const char *ap, const char *passPhrase);
+
+    /**
+    * Disconnect ISM43362 from AP
+    *
+    * @return true only if ISM43362 is disconnected successfully
+    */
+    bool disconnect(void);
+
+    /**
+    * Get the IP address of ISM43362
+    *
+    * @return null-teriminated IP address or null if no IP address is assigned
+    */
+    const char *getIPAddress(void);
+
+    /**
+    * Get the MAC address of ISM43362
+    *
+    * @return null-terminated MAC address or null if no MAC address is assigned
+    */
+    const char *getMACAddress(void);
+
+     /** Get the local gateway
+     *
+     *  @return         Null-terminated representation of the local gateway
+     *                  or null if no network mask has been recieved
+     */
+    const char *getGateway();
+
+    /** Get the local network mask
+     *
+     *  @return         Null-terminated representation of the local network mask 
+     *                  or null if no network mask has been recieved
+     */
+    const char *getNetmask();
+
+    /* Return RSSI for active connection
+     *
+     * @return      Measured RSSI
+     */
+    int8_t getRSSI();
+
+    /**
+    * Check if ISM43362 is conenected
+    *
+    * @return true only if the chip has an IP address
+    */
+    bool isConnected(void);
+
+    /** Scan for available networks
+     *
+     * @param  ap    Pointer to allocated array to store discovered AP
+     * @param  limit Size of allocated @a res array, or 0 to only count available AP
+     * @return       Number of entries in @a res, or if @a count was 0 number of available networks, negative on error
+     *               see @a nsapi_error
+     */
+    int scan(WiFiAccessPoint *res, unsigned limit);
+    
+    /**Perform a dns query
+    *
+    * @param name Hostname to resolve
+    * @param ip   Buffer to store IP address
+    * @return 0 true on success, false on failure
+    */
+    bool dns_lookup(const char *name, char *ip);
+
+    /**
+    * Open a socketed connection
+    *
+    * @param type the type of socket to open "UDP" or "TCP"
+    * @param id id to give the new socket, valid 0-4
+    * @param port port to open connection with
+    * @param addr the IP address of the destination
+    * @return true only if socket opened successfully
+    */
+    bool open(const char *type, int id, const char* addr, int port);
+
+    /**
+    * Sends data to an open socket
+    *
+    * @param id id of socket to send to
+    * @param data data to be sent
+    * @param amount amount of data to be sent - max 1024
+    * @return true only if data sent successfully
+    */
+    bool send(int id, const void *data, uint32_t amount);
+
+    /**
+    * Receives data from an open socket
+    *
+    * @param id id to receive from
+    * @param data placeholder for returned information
+    * @param amount number of bytes to be received
+    * @return the number of bytes received
+    */
+    int32_t recv(int id, void *data, uint32_t amount);
+
+    /**
+    * Closes a socket
+    *
+    * @param id id of socket to close, valid only 0-4
+    * @return true only if socket is closed successfully
+    */
+    bool close(int id);
+
+    /**
+    * Allows timeout to be changed between commands
+    *
+    * @param timeout_ms timeout of the connection
+    */
+    void setTimeout(uint32_t timeout_ms);
+
+    /**
+    * Checks if data is available
+    */
+    bool readable();
+
+    /**
+    * Checks if data can be written
+    */
+    bool writeable();
+
+    /**
+    * Attach a function to call whenever network state has changed
+    *
+    * @param func A pointer to a void function, or 0 to set as none
+    */
+    void attach(Callback<void()> func);
+
+    /**
+    * Check is datas are available to read for a socket
+    * @param id socket id
+    * @param data placeholder for returned information
+    * @param amount size to read for the check
+    * @return amount of read value, or -1 for errors
+    */
+    int check_recv_status(int id, void *data);
+    
+    /**
+    * Attach a function to call whenever network state has changed
+    *
+    * @param obj pointer to the object to call the member function on
+    * @param method pointer to the member function to call
+    */
+    template <typename T, typename M>
+    void attach(T *obj, M method) {
+        attach(Callback<void()>(obj, method));
+    }
+
+private:
+    BufferedSpi _bufferspi;
+    ATParser _parser;
+    DigitalOut _resetpin;
+    volatile int _timeout;
+    volatile int _active_id;
+    void print_rx_buff(void);
+    bool check_response(void);
+    struct packet {
+        struct packet *next;
+        int id;
+        uint32_t len;
+        // data follows
+    } *_packets, **_packets_end;
+    void _packet_handler();
+
+    char _ip_buffer[16];
+    char _gateway_buffer[16];
+    char _netmask_buffer[16];
+    char _mac_buffer[18];
+    char _fw_version[16];
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/ISM43362Interface.cpp	Wed Oct 28 07:42:46 2020 +0000
@@ -0,0 +1,505 @@
+/* ISM43362 implementation of NetworkInterfaceAPI
+ * Copyright (c) STMicroelectronics 2017
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string.h>
+#include "ISM43362Interface.h"
+#include "mbed_debug.h"
+
+// ao activate  / de-activate debug
+#define ism_debug false
+
+// Various timeouts for different ISM43362 operations
+#define ISM43362_CONNECT_TIMEOUT 15000 /* milliseconds */
+#define ISM43362_SEND_TIMEOUT    1000   /* milliseconds */
+#define ISM43362_RECV_TIMEOUT    100   /* milliseconds */
+#define ISM43362_MISC_TIMEOUT    100   /* milliseconds */
+
+// Tested firmware versions
+// Example of versions string returned by the module:
+// "ISM43362-M3G-L44-SPI,C3.5.2.3.BETA9,v3.5.2,v1.4.0.rc1,v8.2.1,120000000,Inventek eS-WiFi"
+// "ISM43362-M3G-L44-SPI,C3.5.2.2,v3.5.2,v1.4.0.rc1,v8.2.1,120000000,Inventek eS-WiFi"
+// Only the first version is checked !
+const char supported_fw_versions[2][15] = {"C3.5.2.3.BETA9", "C3.5.2.2"};
+
+#define MIN(a,b) (((a)<(b))?(a):(b))
+
+// ISM43362Interface implementation
+ISM43362Interface::ISM43362Interface(PinName mosi, PinName miso, PinName sclk, PinName nss, PinName reset, PinName datareadypin, PinName wakeup, bool debug)
+    : _ism(mosi, miso, sclk, nss, reset, datareadypin, wakeup, debug)
+{
+    memset(_ids, 0, sizeof(_ids));
+    memset(_socket_obj, 0, sizeof(_socket_obj));
+    memset(_cbs, 0, sizeof(_cbs));
+    thread_read_socket.start(callback(this, &ISM43362Interface::socket_check_read));
+}
+
+int ISM43362Interface::connect(const char *ssid, const char *pass, nsapi_security_t security,
+                                        uint8_t channel)
+{
+    if (channel != 0) {
+        return NSAPI_ERROR_UNSUPPORTED;
+    }
+
+    set_credentials(ssid, pass, security);
+    return connect();
+}
+
+int ISM43362Interface::connect()
+{
+    _mutex.lock();
+    const char* read_version;
+
+    _ism.setTimeout(ISM43362_MISC_TIMEOUT);
+
+    // Check all supported firmware versions
+    read_version = _ism.get_firmware_version();
+
+    if (!read_version) {
+        debug_if(ism_debug, "ISM43362: ERROR cannot read firmware version\r\n");
+        return NSAPI_ERROR_DEVICE_ERROR;
+    }
+    debug_if(ism_debug, "ISM43362: read_version = [%s]\r\n", read_version);
+
+    if ((strcmp(read_version, supported_fw_versions[0]) == 0) || (strcmp(read_version, supported_fw_versions[1]) == 0)) {
+        debug_if(ism_debug, "ISM43362: firmware version is OK\r\n");
+    } else {
+        debug_if(ism_debug, "ISM43362: WARNING this firmware version has not been tested !\r\n");
+    }
+
+    if (!_ism.dhcp(true)) {
+        return NSAPI_ERROR_DHCP_FAILURE;
+    }
+
+    _ism.setTimeout(ISM43362_CONNECT_TIMEOUT);
+
+    if (!_ism.connect(ap_ssid, ap_pass)) {
+        return NSAPI_ERROR_NO_CONNECTION;
+    }
+
+    _ism.setTimeout(ISM43362_MISC_TIMEOUT);
+    if (!_ism.getIPAddress()) {
+        return NSAPI_ERROR_DHCP_FAILURE;
+    }
+
+    _ism.setTimeout(ISM43362_MISC_TIMEOUT);
+    _mutex.unlock();
+
+    return NSAPI_ERROR_OK;
+}
+
+nsapi_error_t ISM43362Interface::gethostbyname(const char *name, SocketAddress *address, nsapi_version_t version)
+{
+    _mutex.lock();
+    if (address->set_ip_address(name)) {
+        if (version != NSAPI_UNSPEC && address->get_ip_version() != version) {
+            return NSAPI_ERROR_DNS_FAILURE;
+        }
+
+        return NSAPI_ERROR_OK;
+    }
+
+    char *ipbuff = new char[NSAPI_IP_SIZE];
+    int ret = 0;
+    _ism.setTimeout(ISM43362_CONNECT_TIMEOUT);
+    if(!_ism.dns_lookup(name, ipbuff)) {
+        ret = NSAPI_ERROR_DEVICE_ERROR;
+    } else {
+        address->set_ip_address(ipbuff);
+    }
+    _mutex.unlock();
+
+    delete[] ipbuff;
+
+    return ret;
+}
+
+int ISM43362Interface::set_credentials(const char *ssid, const char *pass, nsapi_security_t security)
+{
+    _mutex.lock();
+
+    memset(ap_ssid, 0, sizeof(ap_ssid));
+    strncpy(ap_ssid, ssid, sizeof(ap_ssid));
+
+    memset(ap_pass, 0, sizeof(ap_pass));
+    strncpy(ap_pass, pass, sizeof(ap_pass));
+
+    ap_sec = security;
+    _mutex.unlock();
+
+    return 0;
+}
+
+int ISM43362Interface::set_channel(uint8_t channel)
+{
+    return NSAPI_ERROR_UNSUPPORTED;
+}
+
+int ISM43362Interface::disconnect()
+{
+    _mutex.lock();
+
+    _ism.setTimeout(ISM43362_MISC_TIMEOUT);
+
+    if (!_ism.disconnect()) {
+        return NSAPI_ERROR_DEVICE_ERROR;
+    }
+
+    _mutex.unlock();
+
+    return NSAPI_ERROR_OK;
+}
+
+const char *ISM43362Interface::get_ip_address()
+{
+    _mutex.lock();
+    const char *ret = _ism.getIPAddress();
+    _mutex.unlock();
+    return ret;
+}
+
+const char *ISM43362Interface::get_mac_address()
+{
+    _mutex.lock();
+    const char *ret = _ism.getMACAddress();
+    _mutex.unlock();
+    return ret;
+}
+
+const char *ISM43362Interface::get_gateway()
+{
+    _mutex.lock();
+    const char *ret = _ism.getGateway();
+    _mutex.unlock();
+    return ret;
+}
+
+const char *ISM43362Interface::get_netmask()
+{
+    _mutex.lock();
+    const char *ret = _ism.getNetmask();
+    _mutex.unlock();
+    return ret;
+}
+
+int8_t ISM43362Interface::get_rssi()
+{
+    _mutex.lock();
+    int8_t ret = _ism.getRSSI();
+    _mutex.unlock();
+    return ret;
+}
+
+int ISM43362Interface::scan(WiFiAccessPoint *res, unsigned count)
+{
+    _mutex.lock();
+    _ism.setTimeout(ISM43362_CONNECT_TIMEOUT);
+    int ret = _ism.scan(res, count);
+    _mutex.unlock();
+    return ret;
+}
+
+struct ISM43362_socket {
+    int id;
+    nsapi_protocol_t proto;
+    volatile bool connected;
+    SocketAddress addr;
+    char read_data[1400];
+    volatile uint32_t read_data_size;
+};
+
+int ISM43362Interface::socket_open(void **handle, nsapi_protocol_t proto)
+{
+    // Look for an unused socket
+    int id = -1;
+    for (int i = 0; i < ISM43362_SOCKET_COUNT; i++) {
+        if (!_ids[i]) {
+            id = i;
+            _ids[i] = true;
+            break;
+        }
+    }
+
+    if (id == -1) {
+        return NSAPI_ERROR_NO_SOCKET;
+    }
+    _mutex.lock();
+    struct ISM43362_socket *socket = new struct ISM43362_socket;
+    if (!socket) {
+        return NSAPI_ERROR_NO_SOCKET;
+    }
+    socket->id = id;
+    debug_if(ism_debug, "socket_open, id=%d", socket->id);
+    memset(socket->read_data, 0, sizeof(socket->read_data));
+    socket->addr = 0;
+    socket->read_data_size = 0;
+    socket->proto = proto;
+    socket->connected = false;
+    *handle = socket;
+    _mutex.unlock();
+
+    return 0;
+}
+
+int ISM43362Interface::socket_close(void *handle)
+{
+    _mutex.lock();
+    struct ISM43362_socket *socket = (struct ISM43362_socket *)handle;
+    debug_if(ism_debug, "socket_close, id=%d", socket->id);
+    int err = 0;
+    _ism.setTimeout(ISM43362_MISC_TIMEOUT);
+ 
+    if (!_ism.close(socket->id)) {
+        err = NSAPI_ERROR_DEVICE_ERROR;
+    }
+
+    socket->connected = false;
+    _ids[socket->id] = false;
+    _socket_obj[socket->id] = 0;
+    _mutex.unlock();
+    delete socket;
+    return err;
+}
+
+int ISM43362Interface::socket_bind(void *handle, const SocketAddress &address)
+{
+    return NSAPI_ERROR_UNSUPPORTED;
+}
+
+int ISM43362Interface::socket_listen(void *handle, int backlog)
+{
+    return NSAPI_ERROR_UNSUPPORTED;
+}
+
+int ISM43362Interface::socket_connect(void *handle, const SocketAddress &addr)
+{
+    _mutex.lock();
+    int ret = socket_connect_nolock(handle, addr);
+    _mutex.unlock();
+    return ret;
+}
+
+int ISM43362Interface::socket_connect_nolock(void *handle, const SocketAddress &addr)
+{
+    struct ISM43362_socket *socket = (struct ISM43362_socket *)handle;
+    _ism.setTimeout(ISM43362_CONNECT_TIMEOUT);
+    const char *proto = (socket->proto == NSAPI_UDP) ? "1" : "0";
+    if (!_ism.open(proto, socket->id, addr.get_ip_address(), addr.get_port())) {
+        return NSAPI_ERROR_DEVICE_ERROR;
+    }
+    _ids[socket->id]  = true;
+    _socket_obj[socket->id] = (uint32_t)socket;
+    socket->connected = true;
+    return 0;
+
+}
+
+
+
+void ISM43362Interface::socket_check_read()
+{
+    while (1) {
+        for (int i = 0; i < ISM43362_SOCKET_COUNT; i++) {
+            _mutex.lock();
+            if (_socket_obj[i] != 0) {
+                struct ISM43362_socket *socket = (struct ISM43362_socket *)_socket_obj[i];
+                /* Check if there is something to read for this socket. But if it */
+                /* has already been read : don't read again */
+                if ((socket->connected) && (socket->read_data_size == 0) && _cbs[socket->id].callback) {
+                    _ism.setTimeout(1);
+                    /* if no callback is set, no need to read ?*/
+                    int read_amount = _ism.check_recv_status(socket->id, socket->read_data);
+                    if (read_amount > 0) {
+                        socket->read_data_size = read_amount;
+                    } else if (read_amount < 0) {
+                        /* Mark donw connection has been lost or closed */
+                        socket->connected = false;
+                    }
+                    if (read_amount != 0) {
+                        /* There is something to read in this socket*/
+                        if (_cbs[socket->id].callback) {
+                            _cbs[socket->id].callback(_cbs[socket->id].data);
+                       }
+                    }
+                }
+            }
+            _mutex.unlock();
+        }
+        wait_ms(50);
+    }
+}
+
+int ISM43362Interface::socket_accept(void *server, void **socket, SocketAddress *addr)
+{
+    return NSAPI_ERROR_UNSUPPORTED;
+}
+
+int ISM43362Interface::socket_send(void *handle, const void *data, unsigned size)
+{
+    _mutex.lock();
+    int ret = socket_send_nolock(handle, data, size);
+    _mutex.unlock();
+    return ret;
+}
+
+/*  CAREFULL LOCK must be taken before callling this function */
+int ISM43362Interface::socket_send_nolock(void *handle, const void *data, unsigned size)
+{
+    struct ISM43362_socket *socket = (struct ISM43362_socket *)handle;
+    _ism.setTimeout(ISM43362_SEND_TIMEOUT);
+
+    if (size > ES_WIFI_MAX_TX_PACKET_SIZE) {
+        size = ES_WIFI_MAX_TX_PACKET_SIZE;
+    }
+
+    if (!_ism.send(socket->id, data, size)) {
+        debug_if(ism_debug, "socket_send ERROR\r\n");
+        return NSAPI_ERROR_DEVICE_ERROR; // or WOULD_BLOCK ?
+    }
+
+    return size;
+}
+
+int ISM43362Interface::socket_recv(void *handle, void *data, unsigned size)
+{
+    _mutex.lock();
+    unsigned recv = 0;
+    struct ISM43362_socket *socket = (struct ISM43362_socket *)handle;
+    char *ptr = (char *)data;
+
+    debug_if(ism_debug, "[socket_recv] req=%d\r\n", size);
+
+    if (!socket->connected) {
+        _mutex.unlock();
+        return NSAPI_ERROR_CONNECTION_LOST;
+    }
+
+    _ism.setTimeout(ISM43362_RECV_TIMEOUT);
+
+    if (socket->read_data_size == 0) {
+        /* if no callback is set, no need to read ?*/
+        int read_amount = _ism.check_recv_status(socket->id, socket->read_data);
+        if (read_amount > 0) {
+            socket->read_data_size = read_amount;
+        } else if (read_amount < 0) {
+            socket->connected = false;
+            _mutex.unlock();
+            return NSAPI_ERROR_CONNECTION_LOST;
+        }
+    }
+
+    if (socket->read_data_size != 0) {
+        debug_if(ism_debug, "read_data_size=%d\r\n", socket->read_data_size);
+        uint32_t i=0;
+        while ((i < socket->read_data_size) && (i < size)) {
+            *ptr++ = socket->read_data[i];
+            i++;
+        }
+
+        debug_if(ism_debug, "Copied i bytes=%d, vs %d requestd\r\n", i, size);
+        recv += i;
+
+        if (i >= socket->read_data_size) {
+            /* All the storeed data has been read, reset buffer */
+            memset(socket->read_data, 0, sizeof(socket->read_data));
+            socket->read_data_size = 0;
+            debug_if(ism_debug, "Socket_recv buffer reset\r\n");
+        } else {
+            /*  In case there is remaining data in buffer, update socket content
+             *  For now by shift copy of all data (not very efficient to be
+             *  revised */
+            while (i < socket->read_data_size) {
+                socket->read_data[i - size] = socket->read_data[i];
+                i++;
+            }
+
+            socket->read_data_size -= size;
+        }
+    } else {
+        debug_if(ism_debug, "Nothing in buffer\r\n");
+    }
+
+    debug_if(ism_debug, "[socket_recv]read_datasize=%d, recv=%d\r\n", socket->read_data_size, recv);
+    _mutex.unlock();
+
+    if (recv > 0) {
+        return recv;
+    } else {
+        debug_if(ism_debug, "sock_recv returns WOULD BLOCK\r\n");
+        return NSAPI_ERROR_WOULD_BLOCK;
+    }
+}
+
+int ISM43362Interface::socket_sendto(void *handle, const SocketAddress &addr, const void *data, unsigned size)
+{
+    _mutex.lock();
+    struct ISM43362_socket *socket = (struct ISM43362_socket *)handle;
+
+    if (socket->connected && socket->addr != addr) {
+        _ism.setTimeout(ISM43362_MISC_TIMEOUT);
+        if (!_ism.close(socket->id)) {
+            debug_if(ism_debug, "socket_send ERROR\r\n");
+            _mutex.unlock();
+            return NSAPI_ERROR_DEVICE_ERROR;
+        }
+        socket->connected = false;
+        _ids[socket->id] = false;
+        _socket_obj[socket->id] = 0;
+    }
+
+    if (!socket->connected) {
+        int err = socket_connect_nolock(socket, addr);
+        if (err < 0) {
+            _mutex.unlock();
+            return err;
+        }
+        socket->addr = addr;
+    }
+
+    int ret = socket_send_nolock(socket, data, size);
+
+    _mutex.unlock();
+
+    return ret;
+}
+
+int ISM43362Interface::socket_recvfrom(void *handle, SocketAddress *addr, void *data, unsigned size)
+{
+    int ret = socket_recv(handle, data, size);
+    _mutex.lock();
+    if ((ret >= 0) && addr) {
+        struct ISM43362_socket *socket = (struct ISM43362_socket *)handle;
+        *addr = socket->addr;
+    }
+    _mutex.unlock();
+    return ret;
+}
+
+void ISM43362Interface::socket_attach(void *handle, void (*cb)(void *), void *data)
+{
+    _mutex.lock();
+    struct ISM43362_socket *socket = (struct ISM43362_socket *)handle;
+    _cbs[socket->id].callback = cb;
+    _cbs[socket->id].data = data;
+    _mutex.unlock();
+}
+
+void ISM43362Interface::event() {
+    for (int i = 0; i < ISM43362_SOCKET_COUNT; i++) {
+        if (_cbs[i].callback) {
+            _cbs[i].callback(_cbs[i].data);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/ISM43362Interface.h	Wed Oct 28 07:42:46 2020 +0000
@@ -0,0 +1,300 @@
+/* ISM43362 implementation of NetworkInterfaceAPI
+ * Copyright (c) STMicroelectronics 2017
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ISM43362_INTERFACE_H
+#define ISM43362_INTERFACE_H
+
+#include "mbed.h"
+#include "ISM43362.h"
+
+
+#define ISM43362_SOCKET_COUNT 4
+
+/** ISM43362Interface class
+ *  Implementation of the NetworkStack for the ISM43362
+ */
+class ISM43362Interface : public NetworkStack, public WiFiInterface
+{
+public:
+    /** ISM43362Interface lifetime
+     * @param mosi       MOSI pin
+     * @param miso       MISO pin
+     * @param clk        CLOCK pin
+     * @param nss        NSS pin
+     * @param debug     Enable debugging
+     */
+    ISM43362Interface(PinName mosi, PinName miso, PinName clk, PinName nss, PinName reset, PinName dataready, PinName wakeup, bool debug = false);
+
+    /** Start the interface
+     *
+     *  Attempts to connect to a WiFi network. Requires ssid and passphrase to be set.
+     *  If passphrase is invalid, NSAPI_ERROR_AUTH_ERROR is returned.
+     *
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual int connect();
+
+    /** Start the interface
+     *
+     *  Attempts to connect to a WiFi network.
+     *
+     *  @param ssid      Name of the network to connect to
+     *  @param pass      Security passphrase to connect to the network
+     *  @param security  Type of encryption for connection (Default: NSAPI_SECURITY_NONE)
+     *  @param channel   This parameter is not supported, setting it to anything else than 0 will result in NSAPI_ERROR_UNSUPPORTED
+     *  @return          0 on success, or error code on failure
+     */
+    virtual int connect(const char *ssid, const char *pass, nsapi_security_t security = NSAPI_SECURITY_NONE,
+                                  uint8_t channel = 0);
+    
+    /** Translates a hostname to an IP address with specific version
+     *
+     *  The hostname may be either a domain name or an IP address. If the
+     *  hostname is an IP address, no network transactions will be performed.
+     *
+     *
+     *  @param host     Hostname to resolve
+     *  @param address  Destination for the host SocketAddress
+     *  @param version  IP version of address to resolve, NSAPI_UNSPEC indicates
+     *                  version is chosen by the stack (defaults to NSAPI_UNSPEC)
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual nsapi_error_t gethostbyname(const char *name, SocketAddress *address, nsapi_version_t version = NSAPI_UNSPEC);
+    
+    /** Set the WiFi network credentials
+     *
+     *  @param ssid      Name of the network to connect to
+     *  @param pass      Security passphrase to connect to the network
+     *  @param security  Type of encryption for connection
+     *                   (defaults to NSAPI_SECURITY_NONE)
+     *  @return          0 on success, or error code on failure
+     */
+    virtual int set_credentials(const char *ssid, const char *pass, nsapi_security_t security = NSAPI_SECURITY_NONE);
+
+    /** Set the WiFi network channel - NOT SUPPORTED
+     *
+     * This function is not supported and will return NSAPI_ERROR_UNSUPPORTED
+     *
+     *  @param channel   Channel on which the connection is to be made, or 0 for any (Default: 0)
+     *  @return          Not supported, returns NSAPI_ERROR_UNSUPPORTED
+     */
+    virtual int set_channel(uint8_t channel);
+
+    /** Stop the interface
+     *  @return             0 on success, negative on failure
+     */
+    virtual int disconnect();
+
+    /** Get the internally stored IP address
+     *  @return             IP address of the interface or null if not yet connected
+     */
+    virtual const char *get_ip_address();
+
+    /** Get the internally stored MAC address
+     *  @return             MAC address of the interface
+     */
+    virtual const char *get_mac_address();
+
+     /** Get the local gateway
+     *
+     *  @return         Null-terminated representation of the local gateway
+     *                  or null if no network mask has been recieved
+     */
+    virtual const char *get_gateway();
+
+    /** Get the local network mask
+     *
+     *  @return         Null-terminated representation of the local network mask
+     *                  or null if no network mask has been recieved
+     */
+    virtual const char *get_netmask();
+
+    /** Gets the current radio signal strength for active connection
+     *
+     * @return          Connection strength in dBm (negative value)
+     */
+    virtual int8_t get_rssi();
+
+    /** Scan for available networks
+     *
+     * This function will block.
+     *
+     * @param  ap       Pointer to allocated array to store discovered AP
+     * @param  count    Size of allocated @a res array, or 0 to only count available AP
+     * @param  timeout  Timeout in milliseconds; 0 for no timeout (Default: 0)
+     * @return          Number of entries in @a, or if @a count was 0 number of available networks, negative on error
+     *                  see @a nsapi_error
+     */
+    virtual int scan(WiFiAccessPoint *res, unsigned count);
+
+    /** Translates a hostname to an IP address with specific version
+     *
+     *  The hostname may be either a domain name or an IP address. If the
+     *  hostname is an IP address, no network transactions will be performed.
+     *
+     *  If no stack-specific DNS resolution is provided, the hostname
+     *  will be resolve using a UDP socket on the stack.
+     *
+     *  @param address  Destination for the host SocketAddress
+     *  @param host     Hostname to resolve
+     *  @param version  IP version of address to resolve, NSAPI_UNSPEC indicates
+     *                  version is chosen by the stack (defaults to NSAPI_UNSPEC)
+     *  @return         0 on success, negative error code on failure
+     */
+    using NetworkInterface::gethostbyname;
+
+    /** Add a domain name server to list of servers to query
+     *
+     *  @param addr     Destination for the host address
+     *  @return         0 on success, negative error code on failure
+     */
+    using NetworkInterface::add_dns_server;
+
+protected:
+    /** Open a socket
+     *  @param handle       Handle in which to store new socket
+     *  @param proto        Type of socket to open, NSAPI_TCP or NSAPI_UDP
+     *  @return             0 on success, negative on failure
+     */
+    virtual int socket_open(void **handle, nsapi_protocol_t proto);
+
+    /** Close the socket
+     *  @param handle       Socket handle
+     *  @return             0 on success, negative on failure
+     *  @note On failure, any memory associated with the socket must still
+     *        be cleaned up
+     */
+    virtual int socket_close(void *handle);
+
+    /** Bind a server socket to a specific port
+     *  @param handle       Socket handle
+     *  @param address      Local address to listen for incoming connections on
+     *  @return             0 on success, negative on failure.
+     */
+    virtual int socket_bind(void *handle, const SocketAddress &address);
+
+    /** Start listening for incoming connections
+     *  @param handle       Socket handle
+     *  @param backlog      Number of pending connections that can be queued up at any
+     *                      one time [Default: 1]
+     *  @return             0 on success, negative on failure
+     */
+    virtual int socket_listen(void *handle, int backlog);
+
+    /** Connects this TCP socket to the server
+     *  @param handle       Socket handle
+     *  @param address      SocketAddress to connect to
+     *  @return             0 on success, negative on failure
+     */
+    virtual int socket_connect(void *handle, const SocketAddress &address);
+
+    /** Accept a new connection.
+     *  @param handle       Handle in which to store new socket
+     *  @param server       Socket handle to server to accept from
+     *  @return             0 on success, negative on failure
+     *  @note This call is not-blocking, if this call would block, must
+     *        immediately return NSAPI_ERROR_WOULD_WAIT
+     */
+    virtual int socket_accept(void *handle, void **socket, SocketAddress *address);
+
+    /** Send data to the remote host
+     *  @param handle       Socket handle
+     *  @param data         The buffer to send to the host
+     *  @param size         The length of the buffer to send
+     *  @return             Number of written bytes on success, negative on failure
+     *  @note This call is not-blocking, if this call would block, must
+     *        immediately return NSAPI_ERROR_WOULD_WAIT
+     */
+    virtual int socket_send(void *handle, const void *data, unsigned size);
+
+    /** Receive data from the remote host
+     *  @param handle       Socket handle
+     *  @param data         The buffer in which to store the data received from the host
+     *  @param size         The maximum length of the buffer
+     *  @return             Number of received bytes on success, negative on failure
+     *  @note This call is not-blocking, if this call would block, must
+     *        immediately return NSAPI_ERROR_WOULD_WAIT
+     */
+    virtual int socket_recv(void *handle, void *data, unsigned size);
+
+    /** Send a packet to a remote endpoint
+     *  @param handle       Socket handle
+     *  @param address      The remote SocketAddress
+     *  @param data         The packet to be sent
+     *  @param size         The length of the packet to be sent
+     *  @return             The number of written bytes on success, negative on failure
+     *  @note This call is not-blocking, if this call would block, must
+     *        immediately return NSAPI_ERROR_WOULD_WAIT
+     */
+    virtual int socket_sendto(void *handle, const SocketAddress &address, const void *data, unsigned size);
+
+    /** Receive a packet from a remote endpoint
+     *  @param handle       Socket handle
+     *  @param address      Destination for the remote SocketAddress or null
+     *  @param buffer       The buffer for storing the incoming packet data
+     *                      If a packet is too long to fit in the supplied buffer,
+     *                      excess bytes are discarded
+     *  @param size         The length of the buffer
+     *  @return             The number of received bytes on success, negative on failure
+     *  @note This call is not-blocking, if this call would block, must
+     *        immediately return NSAPI_ERROR_WOULD_WAIT
+     */
+    virtual int socket_recvfrom(void *handle, SocketAddress *address, void *buffer, unsigned size);
+
+    /** Register a callback on state change of the socket
+     *  @param handle       Socket handle
+     *  @param callback     Function to call on state change
+     *  @param data         Argument to pass to callback
+     *  @note Callback may be called in an interrupt context.
+     */
+    virtual void socket_attach(void *handle, void (*callback)(void *), void *data);
+
+    /** Provide access to the NetworkStack object
+     *
+     *  @return The underlying NetworkStack object
+     */
+    virtual NetworkStack *get_stack()
+    {
+        return this;
+    }
+
+private:
+    ISM43362 _ism;
+    bool _ids[ISM43362_SOCKET_COUNT];
+    uint32_t _socket_obj[ISM43362_SOCKET_COUNT]; // store addresses of socket handles
+    Mutex _mutex;
+    Thread thread_read_socket;
+    char ap_ssid[33]; /* 32 is what 802.11 defines as longest possible name; +1 for the \0 */
+    nsapi_security_t ap_sec;
+    uint8_t ap_ch;
+    char ap_pass[64]; /* The longest allowed passphrase */
+
+    void event();
+    struct {
+        void (*callback)(void *);
+        void *data;
+    } _cbs[ISM43362_SOCKET_COUNT];
+
+    /** Function called by the socket read thread to check if data is available on the wifi module
+     *
+     */
+    virtual void socket_check_read();
+    int socket_send_nolock(void *handle, const void *data, unsigned size);
+    int socket_connect_nolock(void *handle, const SocketAddress &addr);
+
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/README.md	Wed Oct 28 07:42:46 2020 +0000
@@ -0,0 +1,50 @@
+# ISM43362 WiFi driver for mbed-os
+The mbed OS driver for the ISM43362 WiFi module
+
+## Currently supported platforms
+ISM43362 module is soldered on the following platforms from STMicroelectronics
+* DISCO_L475VG_IOT01A
+* DISCO_F413ZH
+
+## Configuration
+Add the following lines to the target_overrides section of mbed_app.json of your application
+```
+"DISCO_L475VG_IOT1A": {
+    "wifi-spi_miso": "PC_11",
+    "wifi-spi_mosi": "PC_12",
+    "wifi-spi_sclk": "PC_10",
+    "wifi-spi_nss": "PE_0",
+    "wifi-reset": "PE_8",
+    "wifi-dataready": "PE_1",
+    "wifi-wakeup": "PB_13"
+},
+"DISCO_F413ZH": {
+    "wifi-spi_miso": "PB_4",
+    "wifi-spi_mosi": "PB_5",
+    "wifi-spi_sclk": "PB_12",
+    "wifi-spi_nss": "PG_11",
+    "wifi-reset": "PH_1",
+    "wifi-dataready": "PG_12",
+    "wifi-wakeup": "PB_15"
+}
+```
+
+- MBED_CFG_ISM43362_SSID - SSID of the wifi access point to connect to
+- MBED_CFG_ISM43362_PASS - Passphrase of the wifi access point to connect to
+- MBED_CONF_APP_WIFI_SPI_MISO - spi-miso pin for the ism43362 connection
+- MBED_CONF_APP_WIFI_SPI_MOSI - spi-mosi pin for the ism43362 connection
+- MBED_CONF_APP_WIFI_SPI_SCLK - spi-clock pin for the ism43362 connection
+- MBED_CONF_APP_WIFI_SPI_NSS - spi-nss pin for the ism43362 connection
+- MBED_CONF_APP_WIFI_RESET - Reset pin for the ism43362 wifi module
+- MBED_CONF_APP_WIFI_DATAREADY - Data Ready pin for the ism43362 wifi module
+- MBED_CONF_APP_WIFI_WAKEUP - Wakeup pin for the ism43362 wifi module
+
+
+## Firmware version
+This driver supports ISM43362-M3G-L44-SPI,C3.5.2.3.BETA9 and C3.5.2.2 firmware version
+
+## wifi module FW update
+For more information about the wifi FW version, refer to the detailed procedure in
+http://www.st.com/content/st_com/en/products/embedded-software/mcus-embedded-software/stm32-embedded-software/stm32cube-embedded-software-expansion/x-cube-azure.html
+
+```
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-x-nucleo-idw01m1.lib	Wed Oct 28 07:42:46 2020 +0000
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/wifi-x-nucleo-idw01m1/#5871f7011d7ff2c50e3faf992ebab88e9f69dc95
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-x-nucleo-idw01m1/.gitignore	Wed Oct 28 07:42:46 2020 +0000
@@ -0,0 +1,3 @@
+BUILD
+TESTS
+.mbed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-x-nucleo-idw01m1/BlockExecuter.h	Wed Oct 28 07:42:46 2020 +0000
@@ -0,0 +1,22 @@
+#ifndef BLOCK_EXEC_H
+#define BLOCK_EXEC_H
+
+#include "mbed.h"
+
+/* Helper class to execute something whenever entering/leaving a basic block */
+class BlockExecuter {
+public:
+    BlockExecuter(Callback<void()> exit_cb, Callback<void()> enter_cb = Callback<void()>()) :
+        _exit_cb(exit_cb) {
+        if((bool)enter_cb) enter_cb();
+    }
+
+    ~BlockExecuter(void) {
+        _exit_cb();
+    }
+
+private:
+    Callback<void()> _exit_cb;
+};
+
+#endif  //BLOCK_EXEC_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-x-nucleo-idw01m1/README.md	Wed Oct 28 07:42:46 2020 +0000
@@ -0,0 +1,51 @@
+# Prototype Driver for STM Wi-Fi Expansion Boards based on the SPWFxx Module for STM32 Nucleo #
+
+## Currently supported boards
+ * [X-NUCLEO-IDW01M1](http://www.st.com/content/st_com/en/products/ecosystems/stm32-open-development-environment/stm32-nucleo-expansion-boards/stm32-ode-connect-hw/x-nucleo-idw01m1.html), by setting `mbed` configuration variable `idw0xx1.expansion-board` to value `IDW01M1`
+ * [X-NUCLEO-IDW04A1](http://www.st.com/content/st_com/en/products/ecosystems/stm32-open-development-environment/stm32-nucleo-expansion-boards/stm32-ode-connect-hw/x-nucleo-idw04a1.html), by setting `mbed` configuration variable `idw0xx1.expansion-board` to value `IDW04A1`. You might also need to define macro `IDW04A1_WIFI_HW_BUG_WA`.
+
+## Configuration examples
+
+### Generic concepts
+
+For the ones, which might be less familiar with the **"The mbed configuration system"** in general, here is a [link](https://docs.mbed.com/docs/mbed-os-handbook/en/latest/advanced/config_system/) which points to the latest version of the respective _mbed OS 5 handbook tutorial_.
+
+Furthermore, with respect to this driver, pls. refer to files [`mbed_app_idw01m1.json`](https://github.com/ARMmbed/wifi-x-nucleo-idw01m1/blob/master/mbed_app_idw01m1.json) and [`mbed_app_idw04a1.json`](https://github.com/ARMmbed/wifi-x-nucleo-idw01m1/blob/master/mbed_app_idw04a1.json) for additional reference for what is explained beyond.
+
+### IDW01M1
+
+Add the following lines to the `target_overrides`-section of your `mbed_app.json` file.
+
+``` json
+            "idw0xx1.expansion-board": "IDW01M1",
+            "drivers.uart-serial-txbuf-size": 730,
+            "drivers.uart-serial-rxbuf-size": 730
+```
+
+`IDW01M1` is the default value in the [`mbed_lib.json`](https://github.com/ARMmbed/wifi-x-nucleo-idw01m1/blob/master/mbed_lib.json) file, so setting the expansion board is not mandatory for `IDW01M1`, while setting the TX & RX buffer sizes is highly recommended.
+
+### IDW04A1
+
+Add the following lines to the `target_overrides`-section of your `mbed_app.json` file.
+
+``` json
+            "idw0xx1.expansion-board": "IDW04A1",
+            "drivers.uart-serial-txbuf-size": 750,
+            "drivers.uart-serial-rxbuf-size": 750
+```
+
+### Adding the HW-workaround for IDW04A1
+
+You can add the HW workaround activation macro to the `macros`-section of your `mbed_app.json` file.
+
+``` json
+    "macros": [..., "IDW04A1_WIFI_HW_BUG_WA"]
+```
+
+## Firmware upgrade
+
+Please make sure that you are using the latest firmware available for the expansion boards. For information on how to perform a FW upgrade you may refer to [X-CUBE-WIFI1](http://www.st.com/content/st_com/en/products/embedded-software/mcus-embedded-software/stm32-embedded-software/stm32cube-embedded-software-expansion/x-cube-wifi1.html), especially to document **"X-NUCLEO-IDW0xx1- FW upgrading over UART_v1.2.pdf"** which is contained within folder **"Documentation"** of the X-CUBE-WIFI1 software archive you need to download. 
+
+The actual firmware `.bin` or `.hex` files can be found under 
+- [STSW-WIFI001](http://www.st.com/content/st_com/en/products/embedded-software/wireless-connectivity-software/stsw-wifi001.html) _for what concerns expansion board_ X-NUCLEO-IDW01M1 _and under_
+- [STSW-WIFI004](http://www.st.com/content/st_com/en/products/embedded-software/wireless-connectivity-software/stsw-wifi004.html) _when considering_ X-NUCLEO-IDW04A1.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-x-nucleo-idw01m1/SPWFSA01/SPWFSA01.cpp	Wed Oct 28 07:42:46 2020 +0000
@@ -0,0 +1,258 @@
+/* SPWFSA01 Device
+ * Copyright (c) 2015 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "SPWFSA01.h"
+#include "SpwfSAInterface.h"
+#include "mbed_debug.h"
+
+#if MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW01M1
+
+SPWFSA01::SPWFSA01(PinName tx, PinName rx,
+                   PinName rts, PinName cts,
+                   SpwfSAInterface &ifce, bool debug,
+                   PinName wakeup, PinName reset)
+: SPWFSAxx(tx, rx, rts, cts, ifce, debug, wakeup, reset) {
+}
+
+bool SPWFSA01::open(const char *type, int* spwf_id, const char* addr, int port)
+{
+    int socket_id;
+    int value;
+    int cnt;
+    BH_HANDLER;
+
+    if(!_parser.send("AT+S.SOCKON=%s,%d,%s,ind", addr, port, type))
+    {
+        debug_if(_dbg_on, "\r\nSPWF> `SPWFSA01::open`: error opening socket (%d)\r\n", __LINE__);
+        return false;
+    }
+
+    /* handle both response possibilities here before returning
+     * otherwise module seems to remain in inconsistent state.
+     */
+
+    /* wait for first character */
+    cnt = 0;
+    while((value = _parser.getc()) < 0) {
+        if(cnt++ > SPWFXX_MAX_TRIALS) {
+            debug("\r\nSPWF> error opening socket (%d)\r\n", __LINE__);
+            empty_rx_buffer();
+            return false;
+        }
+    }
+
+    if(value != _cr_) { // Note: this is different to what the spec exactly says
+        debug_if(_dbg_on, "\r\nSPWF> error opening socket (%d)\r\n", __LINE__);
+        empty_rx_buffer();
+        return false;
+    }
+
+    if(!_recv_delim_lf()) { // Note: this is different to what the spec exactly says
+        debug_if(_dbg_on, "\r\nSPWF> error opening socket (%d)\r\n", __LINE__);
+        empty_rx_buffer();
+        return false;
+    }
+
+    value = _parser.getc();
+    switch(value) {
+        case ' ':
+            if(_parser.recv("ID: %d\n", &socket_id)
+                    && _recv_ok()) {
+                debug_if(_dbg_on, "AT^  ID: %d\r\n", socket_id);
+
+                *spwf_id = socket_id;
+                return true;
+            } else {
+                empty_rx_buffer();
+            }
+            break;
+        case 'E':
+            if(_parser.recv("RROR: %[^\n]\n", _err_msg_buffer) && _recv_delim_lf()) {
+                debug_if(_dbg_on, "AT^ ERROR: %s (%d)\r\n", _err_msg_buffer, __LINE__);
+            } else {
+                debug_if(_dbg_on, "\r\nSPWF> error opening socket (%d)\r\n", __LINE__);
+                empty_rx_buffer();
+            }
+            break;
+        default:
+            debug_if(_dbg_on, "\r\nSPWF> error opening socket (%d)\r\n", __LINE__);
+            break;
+    }
+
+    return false;
+}
+
+int SPWFSA01::_read_in(char* buffer, int spwf_id, uint32_t amount) {
+    int ret = -1;
+
+    MBED_ASSERT(buffer != NULL);
+
+    /* block asynchronous indications */
+    if(!_winds_off()) {
+        return -1;
+    }
+
+    /* read in data */
+    if(_parser.send("AT+S.SOCKR=%d,%u", spwf_id, (unsigned int)amount)) {
+        /* set high timeout */
+        _parser.set_timeout(SPWF_READ_BIN_TIMEOUT);
+        /* read in binary data */
+        int read = _parser.read(buffer, amount);
+        /* reset timeout value */
+        _parser.set_timeout(_timeout);
+        if(read > 0) {
+            if(_recv_ok()) {
+                ret = amount;
+            } else {
+                debug_if(_dbg_on, "%s(%d): failed to receive OK\r\n", __func__, __LINE__);
+                empty_rx_buffer();
+            }
+        } else {
+            debug_if(_dbg_on, "%s(%d): failed to read binary data\r\n", __func__, __LINE__);
+            empty_rx_buffer();
+        }
+    } else {
+        debug_if(_dbg_on, "%s(%d): failed to send SOCKR\r\n", __func__, __LINE__);
+    }
+
+    /* unblock asynchronous indications */
+    _winds_on();
+
+    return ret;
+}
+
+bool SPWFSA01::_recv_ap(nsapi_wifi_ap_t *ap)
+{
+    bool ret;
+    unsigned int channel;
+    int cnt;
+
+    ap->security = NSAPI_SECURITY_UNKNOWN;
+
+    /* check for end of list */
+    if(_recv_delim_cr_lf()) {
+        return false;
+    }
+
+    /* run to 'horizontal tab' */
+    cnt = 0;
+    while(_parser.getc() != '\x09') {
+        if(cnt++ > SPWFXX_MAX_TRIALS) {
+            debug("%s (%d) - ERROR: Should never happen!\r\n", __func__, __LINE__);
+            return false;
+        }
+    }
+
+
+    /* read in next line */
+    ret = _parser.recv(" %*s %hhx:%hhx:%hhx:%hhx:%hhx:%hhx CHAN: %u RSSI: %hhd SSID: \'%256[^\']\' CAPS:",
+                       &ap->bssid[0], &ap->bssid[1], &ap->bssid[2], &ap->bssid[3], &ap->bssid[4], &ap->bssid[5],
+                       &channel, &ap->rssi, ssid_buf);
+
+    if(ret) { // ret == true
+        int value;
+
+        /* copy values */
+        memcpy(&ap->ssid, ssid_buf, 32);
+        ap->ssid[32] = '\0';
+        ap->channel = channel;
+
+        /* skip 'CAPS' */
+        for(int i = 0; i < 6; i++) { // read next six characters (" 0421 ")
+            _parser.getc();
+        }
+
+        /* get next character */
+        value = _parser.getc();
+        if(value != 'W') { // no security
+            ap->security = NSAPI_SECURITY_NONE;
+            goto recv_ap_get_out;
+        }
+
+        /* determine security */
+        {
+            char buffer[10];
+
+            if(!_parser.recv("%s%*[\x20]", (char*)&buffer)) {
+                goto recv_ap_get_out;
+            } else if(strncmp("EP", buffer, 10) == 0) {
+                ap->security = NSAPI_SECURITY_WEP;
+                goto recv_ap_get_out;
+            } else if(strncmp("PA2", buffer, 10) == 0) {
+                ap->security = NSAPI_SECURITY_WPA2;
+                goto recv_ap_get_out;
+            } else if(strncmp("PA", buffer, 10) != 0) {
+                goto recv_ap_get_out;
+            }
+
+            /* got a "WPA", check for "WPA2" */
+            value = _parser.getc();
+            if(value == _cr_) { // no further protocol
+                ap->security = NSAPI_SECURITY_WPA;
+                goto recv_ap_get_out;
+            } else { // assume "WPA2"
+                ap->security = NSAPI_SECURITY_WPA_WPA2;
+                goto recv_ap_get_out;
+            }
+        }
+    } else { // ret == false
+        debug("%s (%d) - ERROR: Should never happen!\r\n", __func__, __LINE__);
+    }
+
+recv_ap_get_out:
+    if(ret) { // ret == true
+        /* wait for next line feed */
+        cnt = 0;
+        while(!_recv_delim_lf()) {
+            if(cnt++ > SPWFXX_MAX_TRIALS) {
+                debug("%s (%d) - ERROR: Should never happen!\r\n", __func__, __LINE__);
+                ret = false;
+                break;
+            }
+        }
+    }
+
+    return ret;
+}
+
+int SPWFSA01::scan(WiFiAccessPoint *res, unsigned limit)
+{
+    unsigned cnt = 0;
+    nsapi_wifi_ap_t ap;
+
+    if (!_parser.send("AT+S.SCAN")) {
+        return NSAPI_ERROR_DEVICE_ERROR;
+    }
+
+    while (_recv_ap(&ap)) {
+        if (cnt < limit) {
+            res[cnt] = WiFiAccessPoint(ap);
+        }
+
+        cnt++;
+        if (limit != 0 && cnt >= limit) {
+            break;
+        }
+    }
+
+    if(!_recv_ok()) {
+        empty_rx_buffer();
+    }
+
+    return cnt;
+}
+
+#endif // MBED_CONF_IDW0XX1_EXPANSION_BOARD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-x-nucleo-idw01m1/SPWFSA01/SPWFSA01.h	Wed Oct 28 07:42:46 2020 +0000
@@ -0,0 +1,65 @@
+/* SPWFSA01 Device
+ * Copyright (c) 2015 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+#ifndef SPWFSA01_H
+#define SPWFSA01_H
+
+#include "mbed.h"
+#include "ATCmdParser.h"
+#include "BlockExecuter.h"
+
+#include "./spwfsa01_at_strings.h"
+#include "../SPWFSAxx.h"
+
+class SpwfSAInterface;
+
+/** SPWFSA01 Interface class.
+    This is an interface to a SPWFSA01 module.
+ */
+class SPWFSA01 : public SPWFSAxx
+{
+public:
+    SPWFSA01(PinName tx, PinName rx,
+             PinName rts, PinName cts,
+             SpwfSAInterface &ifce, bool debug,
+             PinName wakeup, PinName reset);
+
+    /**
+     * Open a socketed connection
+     *
+     * @param type the type of socket to open "u" (UDP) or "t" (TCP)
+     * @param id id to get the new socket number, valid 0-7
+     * @param port port to open connection with
+     * @param addr the IP address of the destination
+     * @return true only if socket opened successfully
+     */
+    bool open(const char *type, int* id, const char* addr, int port);
+
+    /** Scan for available networks
+     *
+     * @param  ap    Pointer to allocated array to store discovered AP
+     * @param  limit Size of allocated @a res array, or 0 to only count available AP
+     * @return       Number of entries in @a res, or if @a count was 0 number of available networks, negative on error
+     *               see @a nsapi_error
+     */
+    nsapi_size_or_error_t scan(WiFiAccessPoint *res, unsigned limit);
+
+private:
+    bool _recv_ap(nsapi_wifi_ap_t *ap);
+    int _read_in(char*, int, uint32_t);
+};
+
+#endif // SPWFSA01_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-x-nucleo-idw01m1/SPWFSA01/spwfsa01_at_strings.h	Wed Oct 28 07:42:46 2020 +0000
@@ -0,0 +1,56 @@
+#ifndef SPWFSAXX_AT_STRINGS_H
+#define SPWFSAXX_AT_STRINGS_H
+
+#if defined(TARGET_FF_MORPHO)
+
+#if !defined(SPWFSAXX_WAKEUP_PIN)
+#define SPWFSAXX_WAKEUP_PIN   PC_8                                              // A3
+#endif // !defined(SPWFSAXX_WAKEUP_PIN)
+#if !defined(SPWFSAXX_RESET_PIN)
+#define SPWFSAXX_RESET_PIN    PC_12                                             // D7 / NC
+#endif // !defined(SPWFSAXX_RESET_PIN)
+
+#else // !defined(TARGET_FF_MORPHO)
+
+#if !defined(SPWFSAXX_WAKEUP_PIN)
+#define SPWFSAXX_WAKEUP_PIN   NC                                                // A3
+#endif // !defined(SPWFSAXX_WAKEUP_PIN)
+#if !defined(SPWFSAXX_RESET_PIN)
+#define SPWFSAXX_RESET_PIN    NC                                                // D7 / NC
+#endif // !defined(SPWFSAXX_RESET_PIN)
+
+#endif // !defined(TARGET_FF_MORPHO)
+
+#define SPWFXX_OOB_ERROR            "ERROR:"                                            // "AT-S.ERROR:"
+
+#define SPWFXX_RECV_OK              "OK\n"                                              // "AT-S.OK\n"
+#define SPWFXX_RECV_WIFI_UP         "+WIND:24:WiFi Up:%u.%u.%u.%u\n"                    // "+WIND:24:WiFi Up:%*u:%u.%u.%u.%u\n"
+#define SPWFXX_RECV_IP_ADDR         "#  ip_ipaddr = %u.%u.%u.%u\n"                      // "AT-S.Var:ip_ipaddr=%u.%u.%u.%u\n"
+#define SPWFXX_RECV_GATEWAY         "#  ip_gw = %u.%u.%u.%u\n"                          // "AT-S.Var:ip_gw=%u.%u.%u.%u\n"
+#define SPWFXX_RECV_NETMASK         "#  ip_netmask = %u.%u.%u.%u\n"                     // "AT-S.Var:ip_netmask=%u.%u.%u.%u\n"
+#define SPWFXX_RECV_RX_RSSI         "#  0.rx_rssi = %d\n"                               // "AT-S.Var:0.rx_rssi=%d\n"
+#define SPWFXX_RECV_MAC_ADDR        "#  nv_wifi_macaddr = %x:%x:%x:%x:%x:%x\n"          // "AT-S.Var:nv_wifi_macaddr=%x:%x:%x:%x:%x:%x\n"
+#define SPWFXX_RECV_DATALEN         " DATALEN: %u\n"                                    // "AT-S.Query:%u\n"
+#define SPWFXX_RECV_PENDING_DATA    ":%d:%d\n"                                          // "::%u:%*u:%u\n"
+#define SPWFXX_RECV_SOCKET_CLOSED   ":%d\n"                                             // ":%u:%*u\n"
+
+#define SPWFXX_SEND_FWCFG           "AT&F"                                              // "AT+S.FCFG"
+#define SPWFXX_SEND_DISABLE_LE      "AT+S.SCFG=localecho1,0"                            // "AT+S.SCFG=console_echo,0"
+#define SPWFXX_SEND_DSPLY_CFGV      "AT&V"                                              // "AT+S.GCFG"
+#define SPWFXX_SEND_GET_CONS_STATE  "AT+S.GCFG=console1_enabled"                        // "AT+S.GCFG=console_enabled"
+#define SPWFXX_SEND_GET_CONS_SPEED  "AT+S.GCFG=console1_speed"                          // "AT+S.GCFG=console_speed"
+#define SPWFXX_SEND_GET_HWFC_STATE  "AT+S.GCFG=console1_hwfc"                           // "AT+S.GCFG=console_hwfc"
+#define SPWFXX_SEND_GET_CONS_DELIM  "AT+S.GCFG=console1_delimiter"                      // "AT+S.GCFG=console_delimiter"
+#define SPWFXX_SEND_GET_CONS_ERRS   "AT+S.GCFG=console1_errs"                           // "AT+S.GCFG=console_errs"
+#define SPWFXX_SEND_DISABLE_FC      "AT+S.SCFG=console1_hwfc,0"                         // "AT+S.SCFG=console_hwfc,0"
+#define SPWFXX_SEND_ENABLE_FC       "AT+S.SCFG=console1_hwfc,1"                         // "AT+S.SCFG=console_hwfc,1"
+#define SPWFXX_SEND_SW_RESET        "AT+CFUN=1"                                         // "AT+S.RESET"
+#define SPWFXX_SEND_SAVE_SETTINGS   "AT&W"                                              // "AT+S.WCFG"
+#define SPWFXX_SEND_WIND_OFF_HIGH   "AT+S.SCFG=wind_off_high,"                          // "AT+S.SCFG=console_wind_off_high,"
+#define SPWFXX_SEND_WIND_OFF_MEDIUM "AT+S.SCFG=wind_off_medium,"                        // "AT+S.SCFG=console_wind_off_medium,"
+#define SPWFXX_SEND_WIND_OFF_LOW    "AT+S.SCFG=wind_off_low,"                           // "AT+S.SCFG=console_wind_off_low,"
+
+#define SPWFXX_WINDS_HIGH_ON        "0x00000000"                                        // "0x00100000"
+#define SPWFXX_WINDS_MEDIUM_ON      "0x00000000"                                        // "0x80000000"
+
+#endif // SPWFSAXX_AT_STRINGS_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-x-nucleo-idw01m1/SPWFSA04/SPWFSA04.cpp	Wed Oct 28 07:42:46 2020 +0000
@@ -0,0 +1,286 @@
+/* SPWFSA04 Device
+ * Copyright (c) 2015 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "SPWFSA04.h"
+#include "SpwfSAInterface.h"
+#include "mbed_debug.h"
+
+#if MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1
+
+SPWFSA04::SPWFSA04(PinName tx, PinName rx,
+                   PinName rts, PinName cts,
+                   SpwfSAInterface &ifce, bool debug,
+                   PinName wakeup, PinName reset)
+: SPWFSAxx(tx, rx, rts, cts, ifce, debug, wakeup, reset) {
+}
+
+bool SPWFSA04::open(const char *type, int* spwf_id, const char* addr, int port)
+{
+    int socket_id;
+    int value;
+    int cnt;
+    BH_HANDLER;
+
+    if(!_parser.send("AT+S.SOCKON=%s,%d,NULL,%s", addr, port, type))
+    {
+        debug_if(_dbg_on, "\r\nSPWF> `SPWFSA04::open`: error opening socket (%d)\r\n", __LINE__);
+        return false;
+    }
+
+    /* handle both response possibilities here before returning
+     * otherwise module seems to remain in inconsistent state.
+     */
+
+    if(!_parser.recv("AT-S.")) { // get prefix
+        debug_if(_dbg_on, "\r\nSPWF> `SPWFSA04::open`: error opening socket (%d)\r\n", __LINE__);
+        empty_rx_buffer();
+        return false;
+    }
+
+    /* wait for next character */
+    cnt = 0;
+    while((value = _parser.getc()) < 0) {
+        if(cnt++ > SPWFXX_MAX_TRIALS) {
+            debug("\r\nSPWF> `SPWFSA04::open`: error opening socket (%d)\r\n", __LINE__);
+            empty_rx_buffer();
+            return false;
+        }
+    }
+
+    switch(value) {
+        case 'O':
+            /* get next character */
+            value = _parser.getc();
+            if(value != 'n') {
+                debug_if(_dbg_on, "\r\nSPWF> `SPWFSA04::open`: error opening socket (%d)\r\n", __LINE__);
+                empty_rx_buffer();
+                return false;
+            }
+
+            /* get socket id */
+            if(!(_parser.recv(":%*u.%*u.%*u.%*u:%d\n", &socket_id)
+                    && _recv_delim_lf()
+                    && _recv_ok())) {
+                debug_if(_dbg_on, "\r\nSPWF> `SPWFSA04::open`: error opening socket (%d)\r\n", __LINE__);
+                empty_rx_buffer();
+                return false;
+            }
+            debug_if(_dbg_on, "AT^ AT-S.On:%s:%d\r\n", addr, socket_id);
+
+            *spwf_id = socket_id;
+            return true;
+        case 'E':
+            int err_nr;
+            if(_parser.recv("RROR:%d:%[^\n]\n", &err_nr, _err_msg_buffer) && _recv_delim_lf()) {
+                debug_if(_dbg_on, "AT^ AT-S.ERROR:%d:%s (%d)\r\n", err_nr, _err_msg_buffer, __LINE__);
+            } else {
+                debug_if(_dbg_on, "\r\nSPWF> `SPWFSA04::open`: error opening socket (%d)\r\n", __LINE__);
+                empty_rx_buffer();
+            }
+            break;
+        default:
+            debug_if(_dbg_on, "\r\nSPWF> `SPWFSA04::open`: error opening socket (%d)\r\n", __LINE__);
+            empty_rx_buffer();
+            break;
+    }
+
+    return false;
+}
+
+int SPWFSA04::_read_in(char* buffer, int spwf_id, uint32_t amount) {
+    int ret = -1;
+    int received, cumulative;
+
+    MBED_ASSERT(buffer != NULL);
+
+    /* block asynchronous indications */
+    if(!_winds_off()) {
+        return -1;
+    }
+
+    /* read in data */
+    if(_parser.send("AT+S.SOCKR=%d,%d", spwf_id, (unsigned int)amount)) {
+        if(!(_parser.recv("AT-S.Reading:%d:%d\n", &received, &cumulative) &&
+                _recv_delim_lf())) {
+            debug_if(_dbg_on, "%s(%d): failed to receive AT-S.Reading\r\n", __func__, __LINE__);
+            empty_rx_buffer();
+        } else {
+            /* set high timeout */
+            _parser.set_timeout(SPWF_READ_BIN_TIMEOUT);
+            /* read in binary data */
+            int read = _parser.read(buffer, amount);
+            /* reset timeout value */
+            _parser.set_timeout(_timeout);
+            if(read > 0) {
+                if(_recv_ok()) {
+                    ret = amount;
+                } else {
+                    debug_if(_dbg_on, "%s(%d): failed to receive OK\r\n", __func__, __LINE__);
+                    empty_rx_buffer();
+                }
+            } else {
+                debug_if(_dbg_on, "%s(%d): failed to read binary data\r\n", __func__, __LINE__);
+                empty_rx_buffer();
+            }
+        }
+    } else {
+        debug_if(_dbg_on, "%s(%d): failed to send SOCKR\r\n", __func__, __LINE__);
+    }
+
+    /* unblock asynchronous indications */
+    _winds_on();
+
+    return ret;
+}
+
+bool SPWFSA04::_recv_ap(nsapi_wifi_ap_t *ap)
+{
+    bool ret;
+    int curr;
+    unsigned int channel;
+    int cnt;
+
+    ap->security = NSAPI_SECURITY_UNKNOWN;
+
+    /* determine list end */
+    curr = _parser.getc();
+    if(curr == 'A') { // assume end of list ("AT-S.OK")
+        if(!(_parser.recv("T-S.OK\n") && _recv_delim_lf())) {
+            empty_rx_buffer();
+        }
+        return false;
+    }
+
+    /* run to 'horizontal tab' */
+    cnt = 0;
+    while(_parser.getc() != '\x09') {
+        if(cnt++ > SPWFXX_MAX_TRIALS) {
+            debug("%s (%d) - ERROR: Should never happen!\r\n", __func__, __LINE__);
+            empty_rx_buffer();
+            return false;
+        }
+    }
+
+    /* read in next line */
+    ret = _parser.recv(" %*s %hhx:%hhx:%hhx:%hhx:%hhx:%hhx CHAN: %u RSSI: %hhd SSID: \'%256[^\']\' CAPS:",
+                       &ap->bssid[0], &ap->bssid[1], &ap->bssid[2], &ap->bssid[3], &ap->bssid[4], &ap->bssid[5],
+                       &channel, &ap->rssi, ssid_buf);
+
+    if(ret) { // ret == true
+        int value;
+
+        /* copy values */
+        memcpy(&ap->ssid, ssid_buf, 32);
+        ap->ssid[32] = '\0';
+        ap->channel = channel;
+
+        /* skip 'CAPS' */
+        for(int i = 0; i < 6; i++) { // read next six characters (" 0421 ")
+            _parser.getc();
+        }
+
+        /* get next character */
+        value = _parser.getc();
+        if(value != 'W') { // no security
+            ap->security = NSAPI_SECURITY_NONE;
+            goto recv_ap_get_out;
+        }
+
+        /* determine security */
+        {
+            char buffer[10];
+
+            if(!_parser.recv("%s%*[\x20]", (char*)&buffer)) {
+                goto recv_ap_get_out;
+            } else if(strncmp("EP", buffer, 10) == 0) {
+                ap->security = NSAPI_SECURITY_WEP;
+                goto recv_ap_get_out;
+            } else if(strncmp("PA2", buffer, 10) == 0) {
+                ap->security = NSAPI_SECURITY_WPA2;
+                goto recv_ap_get_out;
+            } else if(strncmp("PA", buffer, 10) != 0) {
+                goto recv_ap_get_out;
+            }
+
+            /* got a "WPA", check for "WPA2" */
+            value = _parser.getc();
+            if(value == _cr_) { // no further protocol
+                ap->security = NSAPI_SECURITY_WPA;
+                goto recv_ap_get_out;
+            } else { // assume "WPA2"
+                ap->security = NSAPI_SECURITY_WPA_WPA2;
+                goto recv_ap_get_out;
+            }
+        }
+    } else { // ret == false
+        debug("%s (%d) - ERROR: Should never happen!\r\n", __func__, __LINE__);
+        empty_rx_buffer();
+    }
+
+recv_ap_get_out:
+    if(ret) { // ret == true
+        /* wait for next line feed */
+        cnt = 0;
+        while(!_recv_delim_lf()) {
+            if(cnt++ > SPWFXX_MAX_TRIALS) {
+                debug("%s (%d) - ERROR: Should never happen!\r\n", __func__, __LINE__);
+                empty_rx_buffer();
+                ret = false;
+                break;
+            }
+        }
+    }
+
+    return ret;
+}
+
+nsapi_size_or_error_t SPWFSA04::scan(WiFiAccessPoint *res, unsigned limit)
+{
+    unsigned int cnt = 0, found;
+    nsapi_wifi_ap_t ap;
+
+    if (!_parser.send("AT+S.SCAN=s,")) {
+        return NSAPI_ERROR_DEVICE_ERROR;
+    }
+
+    if(!(_parser.recv("AT-S.Parsing Networks:%u\n", &found) && _recv_delim_lf())) {
+        debug_if(_dbg_on, "SPWF> error start network scanning\r\n");
+        empty_rx_buffer();
+        return NSAPI_ERROR_DEVICE_ERROR;
+    }
+
+    debug_if(_dbg_on, "AT^ AT-S.Parsing Networks:%u\r\n", found);
+
+    if(found > 0) {
+        while (_recv_ap(&ap)) {
+            if (cnt < limit) {
+                res[cnt] = WiFiAccessPoint(ap);
+            }
+
+            if (!((limit != 0) && ((cnt + 1) > limit))) {
+                cnt++;
+            }
+        }
+    } else {
+        if(!_recv_ok()) {
+            empty_rx_buffer();
+        }
+    }
+
+    return cnt;
+}
+
+#endif // MBED_CONF_IDW0XX1_EXPANSION_BOARD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-x-nucleo-idw01m1/SPWFSA04/SPWFSA04.h	Wed Oct 28 07:42:46 2020 +0000
@@ -0,0 +1,65 @@
+/* SPWFSA04 Device
+ * Copyright (c) 2015 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+#ifndef SPWFSA04_H
+#define SPWFSA04_H
+
+#include "mbed.h"
+#include "ATCmdParser.h"
+#include "BlockExecuter.h"
+
+#include "./spwfsa04_at_strings.h"
+#include "../SPWFSAxx.h"
+
+class SpwfSAInterface;
+
+/** SPWFSA04 Interface class.
+    This is an interface to a SPWFSA04 module.
+ */
+class SPWFSA04 : public SPWFSAxx
+{
+public:
+    SPWFSA04(PinName tx, PinName rx,
+             PinName rts, PinName cts,
+             SpwfSAInterface &ifce, bool debug,
+             PinName wakeup, PinName reset);
+
+    /**
+     * Open a socketed connection
+     *
+     * @param type the type of socket to open "u" (UDP) or "t" (TCP)
+     * @param id id to get the new socket number, valid 0-7
+     * @param port port to open connection with
+     * @param addr the IP address of the destination
+     * @return true only if socket opened successfully
+     */
+    bool open(const char *type, int* id, const char* addr, int port);
+
+    /** Scan for available networks
+     *
+     * @param  ap    Pointer to allocated array to store discovered AP
+     * @param  limit Size of allocated @a res array, or 0 to only count available AP
+     * @return       Number of entries in @a res, or if @a count was 0 number of available networks, negative on error
+     *               see @a nsapi_error
+     */
+    nsapi_size_or_error_t scan(WiFiAccessPoint *res, unsigned limit);
+
+private:
+    bool _recv_ap(nsapi_wifi_ap_t *ap);
+    int _read_in(char*, int, uint32_t);
+};
+
+#endif // SPWFSA04_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-x-nucleo-idw01m1/SPWFSA04/spwfsa04_at_strings.h	Wed Oct 28 07:42:46 2020 +0000
@@ -0,0 +1,63 @@
+#ifndef SPWFSAXX_AT_STRINGS_H
+#define SPWFSAXX_AT_STRINGS_H
+
+/* Define beyond macro if your X-NUCLEO-IDW04A1 expansion board has NOT the `WIFI_RST` HW patch applied on it */
+// #define IDW04A1_WIFI_HW_BUG_WA // delegated to mbed config system
+
+#if defined(TARGET_FF_ARDUINO)
+
+#if !defined(SPWFSAXX_WAKEUP_PIN)
+#define SPWFSAXX_WAKEUP_PIN   A3
+#endif
+#if !defined(SPWFSAXX_RESET_PIN)
+#ifndef IDW04A1_WIFI_HW_BUG_WA
+#define SPWFSAXX_RESET_PIN    D7
+#else // IDW04A1_WIFI_HW_PATCH
+#define SPWFSAXX_RESET_PIN    NC
+#endif // !IDW04A1_WIFI_HW_PATCH
+#endif
+
+#else // !defined(TARGET_FF_ARDUINO)
+
+#if !defined(SPWFSAXX_WAKEUP_PIN)
+#define SPWFSAXX_WAKEUP_PIN   NC
+#endif
+#if !defined(SPWFSAXX_RESET_PIN)
+#define SPWFSAXX_RESET_PIN    NC
+#endif
+
+#endif // !defined(TARGET_FF_ARDUINO)
+
+#define SPWFXX_OOB_ERROR            "AT-S.ERROR:"                                           // "ERROR:"
+
+#define SPWFXX_RECV_OK              "AT-S.OK\n"                                             // "OK\n"
+#define SPWFXX_RECV_WIFI_UP         "+WIND:24:WiFi Up:%*u:%u.%u.%u.%u\n"                    // "+WIND:24:WiFi Up:%u.%u.%u.%u\n"
+#define SPWFXX_RECV_IP_ADDR         "AT-S.Var:ip_ipaddr=%u.%u.%u.%u\n"                      // "#  ip_ipaddr = %u.%u.%u.%u\n"
+#define SPWFXX_RECV_GATEWAY         "AT-S.Var:ip_gw=%u.%u.%u.%u\n"                          // "#  ip_gw = %u.%u.%u.%u\n"
+#define SPWFXX_RECV_NETMASK         "AT-S.Var:ip_netmask=%u.%u.%u.%u\n"                     // "#  ip_netmask = %u.%u.%u.%u\n"
+#define SPWFXX_RECV_RX_RSSI         "AT-S.Var:0.rx_rssi=%d\n"                               // "#  0.rx_rssi = %d\n"
+#define SPWFXX_RECV_MAC_ADDR        "AT-S.Var:nv_wifi_macaddr=%x:%x:%x:%x:%x:%x\n"          // "#  nv_wifi_macaddr = %x:%x:%x:%x:%x:%x\n"
+#define SPWFXX_RECV_DATALEN         "AT-S.Query:%u\n"                                       // " DATALEN: %u\n"
+#define SPWFXX_RECV_PENDING_DATA    "::%u:%*u:%u\n"                                         // ":%d:%d\n"
+#define SPWFXX_RECV_SOCKET_CLOSED   ":%u:%*u\n"                                             // ":%d\n"
+
+#define SPWFXX_SEND_FWCFG           "AT+S.FCFG"                                             // "AT&F"
+#define SPWFXX_SEND_DISABLE_LE      "AT+S.SCFG=console_echo,0"                              // "AT+S.SCFG=localecho1,0"
+#define SPWFXX_SEND_DSPLY_CFGV      "AT+S.GCFG"                                             // "AT&V"
+#define SPWFXX_SEND_GET_CONS_STATE  "AT+S.GCFG=console_enabled"                             // "AT+S.GCFG=console1_enabled"
+#define SPWFXX_SEND_GET_CONS_SPEED  "AT+S.GCFG=console_speed"                               // "AT+S.GCFG=console1_speed"
+#define SPWFXX_SEND_GET_HWFC_STATE  "AT+S.GCFG=console_hwfc"                                // "AT+S.GCFG=console1_hwfc"
+#define SPWFXX_SEND_GET_CONS_DELIM  "AT+S.GCFG=console_delimiter"                           // "AT+S.GCFG=console1_delimiter"
+#define SPWFXX_SEND_GET_CONS_ERRS   "AT+S.GCFG=console_errs"                                // "AT+S.GCFG=console1_errs"
+#define SPWFXX_SEND_DISABLE_FC      "AT+S.SCFG=console_hwfc,0"                              // "AT+S.SCFG=console1_hwfc,0"
+#define SPWFXX_SEND_ENABLE_FC       "AT+S.SCFG=console_hwfc,1"                              // "AT+S.SCFG=console1_hwfc,1"
+#define SPWFXX_SEND_SW_RESET        "AT+S.RESET"                                            // "AT+CFUN=1"
+#define SPWFXX_SEND_SAVE_SETTINGS   "AT+S.WCFG"                                             // "AT&W"
+#define SPWFXX_SEND_WIND_OFF_HIGH   "AT+S.SCFG=console_wind_off_high,"                      // "AT+S.SCFG=wind_off_high,"
+#define SPWFXX_SEND_WIND_OFF_MEDIUM "AT+S.SCFG=console_wind_off_medium,"                    // "AT+S.SCFG=wind_off_medium,"
+#define SPWFXX_SEND_WIND_OFF_LOW    "AT+S.SCFG=console_wind_off_low,"                       // "AT+S.SCFG=wind_off_low,"
+
+#define SPWFXX_WINDS_HIGH_ON        "0x00100000"                                            // "0x00000000"
+#define SPWFXX_WINDS_MEDIUM_ON      "0x80000000"                                            // "0x00000000"
+
+#endif // SPWFSAXX_AT_STRINGS_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-x-nucleo-idw01m1/SPWFSAxx.cpp	Wed Oct 28 07:42:46 2020 +0000
@@ -0,0 +1,1000 @@
+/* SPWFSAxx Devices
+ * Copyright (c) 2015 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mbed_debug.h"
+
+#include "SpwfSAInterface.h" /* must be included first */
+#include "SPWFSAxx.h"
+
+static const char out_delim[] = {SPWFSAxx::_cr_, '\0'};
+
+SPWFSAxx::SPWFSAxx(PinName tx, PinName rx,
+                   PinName rts, PinName cts,
+                   SpwfSAInterface &ifce, bool debug,
+                   PinName wakeup, PinName reset)
+: _serial(tx, rx, SPWFXX_DEFAULT_BAUD_RATE), _parser(&_serial, out_delim),
+  _wakeup(wakeup, 1), _reset(reset, 1),
+  _rts(rts), _cts(cts),
+  _timeout(SPWF_INIT_TIMEOUT), _dbg_on(debug),
+  _pending_sockets_bitmap(0),
+  _network_lost_flag(false),
+  _associated_interface(ifce),
+  _call_event_callback_blocked(false),
+  _callback_func(),
+  _packets(0), _packets_end(&_packets),
+  _err_msg_buffer(ssid_buf)
+{
+    _serial.set_baud(SPWFXX_DEFAULT_BAUD_RATE);
+    _serial.sigio(Callback<void()>(this, &SPWFSAxx::_event_handler));
+    _parser.debug_on(debug);
+
+    _parser.oob("+WIND:55:Pending Data", callback(this, &SPWFSAxx::_packet_handler_th));
+    _parser.oob("+WIND:58:Socket Closed", callback(this, &SPWFSAxx::_server_gone_handler));
+    _parser.oob("+WIND:33:WiFi Network Lost", callback(this, &SPWFSAxx::_network_lost_handler_th));
+    _parser.oob("+WIND:8:Hard Fault", callback(this, &SPWFSAxx::_hard_fault_handler));
+    _parser.oob("+WIND:5:WiFi Hardware Failure", callback(this, &SPWFSAxx::_wifi_hwfault_handler));
+    _parser.oob(SPWFXX_OOB_ERROR, callback(this, &SPWFSAxx::_error_handler));
+}
+
+bool SPWFSAxx::startup(int mode)
+{
+    /*Reset module*/
+    if(!hw_reset()) {
+        debug_if(_dbg_on, "\r\nSPWF> HW reset failed\r\n");
+        return false;
+    }
+
+    /* factory reset */
+    if(!(_parser.send(SPWFXX_SEND_FWCFG) && _recv_ok()))
+    {
+        debug_if(_dbg_on, "\r\nSPWF> error restore factory default settings\r\n");
+        return false;
+    }
+
+    /*switch off led*/
+    if(!(_parser.send("AT+S.SCFG=blink_led,0") && _recv_ok()))
+    {
+        debug_if(_dbg_on, "\r\nSPWF> error stop blinking led (%d)\r\n", __LINE__);
+        return false;
+    }
+
+    /*set local echo to 0*/
+    if(!(_parser.send(SPWFXX_SEND_DISABLE_LE) && _recv_ok()))
+    {
+        debug_if(_dbg_on, "\r\nSPWF> error local echo set\r\n");
+        return false;
+    }
+
+    /*set Wi-Fi mode and rate to b/g/n*/
+    if(!(_parser.send("AT+S.SCFG=wifi_ht_mode,1") && _recv_ok()))
+    {
+        debug_if(_dbg_on, "\r\nSPWF> error setting ht_mode\r\n");
+        return false;
+    }
+
+    /*set the operational rate*/
+    if(!(_parser.send("AT+S.SCFG=wifi_opr_rate_mask,0x003FFFCF") && _recv_ok()))
+    {
+        debug_if(_dbg_on, "\r\nSPWF> error setting operational rates\r\n");
+        return false;
+    }
+
+    /*set idle mode (0->idle, 1->STA,3->miniAP, 2->IBSS)*/
+    if(!(_parser.send("AT+S.SCFG=wifi_mode,%d", mode) && _recv_ok()))
+    {
+        debug_if(_dbg_on, "\r\nSPWF> error wifi mode set idle (%d)\r\n", __LINE__);
+        return false;
+    }
+
+#if defined(MBED_MAJOR_VERSION)
+#if !DEVICE_SERIAL_FC || (MBED_VERSION < MBED_ENCODE_VERSION(5, 7, 0))
+    /*disable HW flow control*/
+    if(!(_parser.send(SPWFXX_SEND_DISABLE_FC) && _recv_ok()))
+    {
+        debug_if(_dbg_on, "\r\nSPWF> error disabling HW flow control\r\n");
+        return false;
+    }
+#else // DEVICE_SERIAL_FC && (MBED_VERSION >= MBED_ENCODE_VERSION(5, 7, 0))
+    if((_rts != NC) && (_cts != NC)) {
+        /*enable HW flow control*/
+        if(!(_parser.send(SPWFXX_SEND_ENABLE_FC) && _recv_ok()))
+        {
+            debug_if(_dbg_on, "\r\nSPWF> error enabling HW flow control\r\n");
+            return false;
+        }
+
+        /*configure pins for HW flow control*/
+        _serial.set_flow_control(SerialBase::RTSCTS, _rts, _cts);
+    } else {
+        /*disable HW flow control*/
+        if(!(_parser.send(SPWFXX_SEND_DISABLE_FC) && _recv_ok()))
+        {
+            debug_if(_dbg_on, "\r\nSPWF> error disabling HW flow control\r\n");
+            return false;
+        }
+    }
+#endif // DEVICE_SERIAL_FC && (MBED_VERSION >= MBED_ENCODE_VERSION(5, 7, 0))
+#else // !defined(MBED_MAJOR_VERSION) - Assuming `master` branch
+#if !DEVICE_SERIAL_FC
+    /*disable HW flow control*/
+    if(!(_parser.send(SPWFXX_SEND_DISABLE_FC) && _recv_ok()))
+    {
+        debug_if(_dbg_on, "\r\nSPWF> error disabling HW flow control\r\n");
+        return false;
+    }
+#else // DEVICE_SERIAL_FC
+    if((_rts != NC) && (_cts != NC)) {
+        /*enable HW flow control*/
+        if(!(_parser.send(SPWFXX_SEND_ENABLE_FC) && _recv_ok()))
+        {
+            debug_if(_dbg_on, "\r\nSPWF> error enabling HW flow control\r\n");
+            return false;
+        }
+
+        /*configure pins for HW flow control*/
+        _serial.set_flow_control(SerialBase::RTSCTS, _rts, _cts);
+    } else {
+        /*disable HW flow control*/
+        if(!(_parser.send(SPWFXX_SEND_DISABLE_FC) && _recv_ok()))
+        {
+            debug_if(_dbg_on, "\r\nSPWF> error disabling HW flow control\r\n");
+            return false;
+        }
+    }
+#endif // DEVICE_SERIAL_FC
+#endif // !defined(MBED_MAJOR_VERSION)
+
+    /* Disable selected WINDs */
+    _winds_on();
+
+    /* sw reset */
+    if(!reset()) {
+        debug_if(_dbg_on, "\r\nSPWF> SW reset failed (%s, %d)\r\n", __func__, __LINE__);
+        return false;
+    }
+
+#ifndef NDEBUG
+    if (!(_parser.send(SPWFXX_SEND_GET_CONS_STATE)
+            && _recv_ok())) {
+        debug_if(_dbg_on, "\r\nSPWF> error getting console state\r\n");
+        return false;
+    }
+
+    if (!(_parser.send(SPWFXX_SEND_GET_CONS_SPEED)
+            && _recv_ok())) {
+        debug_if(_dbg_on, "\r\nSPWF> error getting console speed\r\n");
+        return false;
+    }
+
+    if (!(_parser.send(SPWFXX_SEND_GET_HWFC_STATE)
+            && _recv_ok())) {
+        debug_if(_dbg_on, "\r\nSPWF> error getting hwfc state\r\n");
+        return false;
+    }
+
+#if (MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1) || defined(IDW01M1_FW_REL_35X)
+    /* betzw: IDW01M1 FW versions <3.5 seem to have problems with the following two commands.
+     *        For the sake of simplicity, just excluding them for IDW01M1 in general.
+     */
+    if (!(_parser.send(SPWFXX_SEND_GET_CONS_DELIM)
+            && _recv_ok())) {
+        debug_if(_dbg_on, "\r\nSPWF> error getting console delimiter\r\n");
+        return false;
+    }
+
+    if (!(_parser.send(SPWFXX_SEND_GET_CONS_ERRS)
+            && _recv_ok())) {
+        debug_if(_dbg_on, "\r\nSPWF> error getting console error setting\r\n");
+        return false;
+    }
+#endif // (MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1) || defined(IDW01M1_FW_REL_35X)
+
+    if (!(_parser.send("AT+S.GCFG=sleep_enabled")
+            && _recv_ok())) {
+        debug_if(_dbg_on, "\r\nSPWF> error getting sleep state enabled\r\n");
+        return false;
+    }
+
+    if (!(_parser.send("AT+S.GCFG=wifi_powersave")
+            && _recv_ok())) {
+        debug_if(_dbg_on, "\r\nSPWF> error getting powersave mode\r\n");
+        return false;
+    }
+
+    if (!(_parser.send("AT+S.GCFG=standby_enabled")
+            && _recv_ok())) {
+        debug_if(_dbg_on, "\r\nSPWF> error getting standby state enabled\r\n");
+        return false;
+    }
+#endif
+
+    return true;
+}
+
+bool SPWFSAxx::_wait_console_active(void) {
+    int cnt = 0;
+
+    while(true) {
+        if (_parser.recv("+WIND:0:Console active\n") && _recv_delim_lf()) {
+            debug_if(_dbg_on, "AT^ +WIND:0:Console active\r\n");
+            return true;
+        }
+        if(cnt++ > SPWFXX_MAX_TRIALS) {
+            debug("%s (%d) - ERROR: Should never happen!\r\n", __func__, __LINE__);
+            empty_rx_buffer();
+            return false;
+        }
+    }
+}
+
+bool SPWFSAxx::_wait_wifi_hw_started(void) {
+    int cnt = 0;
+
+    while(true) {
+        if (_parser.recv("+WIND:32:WiFi Hardware Started\n") && _recv_delim_lf()) {
+            debug_if(_dbg_on, "AT^ +WIND:32:WiFi Hardware Started\r\n");
+            return true;
+        }
+        if(cnt++ > SPWFXX_MAX_TRIALS) {
+            debug("%s (%d) - ERROR: Should never happen!\r\n", __func__, __LINE__);
+            empty_rx_buffer();
+            return false;
+        }
+    }
+}
+
+bool SPWFSAxx::hw_reset(void)
+{
+#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
+    _reset.write(0);
+    wait_ms(200);
+    _reset.write(1); 
+#else // (MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1) && defined(IDW04A1_WIFI_HW_BUG_WA): substitute with SW reset
+    _parser.send(SPWFXX_SEND_SW_RESET);
+#endif // (MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1) && defined(IDW04A1_WIFI_HW_BUG_WA)
+    return _wait_console_active();
+}
+
+bool SPWFSAxx::reset(void)
+{
+    bool ret;
+
+    /* save current setting in flash */
+    if(!(_parser.send(SPWFXX_SEND_SAVE_SETTINGS) && _recv_ok()))
+    {
+        debug_if(_dbg_on, "\r\nSPWF> error saving configuration to flash\r\n");
+        return false;
+    }
+
+    if(!_parser.send(SPWFXX_SEND_SW_RESET)) return false; /* betzw - NOTE: "keep the current state and reset the device".
+                                                                   We assume that the module informs us about the
+                                                                   eventual closing of sockets via "WIND" asynchronous
+                                                                   indications! So everything regarding the clean-up
+                                                                   of these situations is handled there. */
+    ret = _wait_wifi_hw_started();
+
+    return ret;
+}
+
+/* Security Mode
+   None          = 0, 
+   WEP           = 1,
+   WPA_Personal  = 2,
+ */
+bool SPWFSAxx::connect(const char *ap, const char *passPhrase, int securityMode)
+{
+    unsigned int n1, n2, n3, n4;
+    int cnt;
+
+    //AT+S.SCFG=wifi_wpa_psk_text,%s
+    if(!(_parser.send("AT+S.SCFG=wifi_wpa_psk_text,%s", passPhrase) && _recv_ok()))
+    {
+        debug_if(_dbg_on, "\r\nSPWF> error pass set\r\n");
+        return false;
+    } 
+
+    //AT+S.SSIDTXT=%s
+    if(!(_parser.send("AT+S.SSIDTXT=%s", ap) && _recv_ok()))
+    {
+        debug_if(_dbg_on, "\r\nSPWF> error ssid set\r\n");
+        return false;
+    }
+
+    //AT+S.SCFG=wifi_priv_mode,%d
+    if(!(_parser.send("AT+S.SCFG=wifi_priv_mode,%d", securityMode) && _recv_ok()))
+    {
+        debug_if(_dbg_on, "\r\nSPWF> error security mode set\r\n");
+        return false;
+    }
+
+    /*set STA mode (0->idle, 1->STA,3->miniAP, 2->IBSS)*/
+    if(!(_parser.send("AT+S.SCFG=wifi_mode,1") && _recv_ok()))
+    {
+        debug_if(_dbg_on, "\r\nSPWF> error wifi mode set 1 (STA)\r\n");
+        return false;
+    }
+
+    /* sw reset */
+    if(!reset()) {
+        debug_if(_dbg_on, "\r\nSPWF> SW reset failed (%s, %d)\r\n", __func__, __LINE__);
+        return false;
+    }
+
+    cnt = 0;
+    while(true) {
+        if(_parser.recv(SPWFXX_RECV_WIFI_UP, &n1, &n2, &n3, &n4) && _recv_delim_lf())
+        {
+            debug_if(_dbg_on, "AT^ +WIND:24:WiFi Up:%u.%u.%u.%u\r\n", n1, n2, n3, n4);
+            break;
+        }
+        if(cnt++ > SPWFXX_MAX_TRIALS) {
+            debug("%s (%d) - ERROR: Should never happen!\r\n", __func__, __LINE__);
+            empty_rx_buffer();
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool SPWFSAxx::disconnect(void)
+{
+#if MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1
+    /*disable Wi-Fi device*/
+    if(!(_parser.send("AT+S.WIFI=0") && _recv_ok()))
+    {
+        debug_if(_dbg_on, "\r\nSPWF> error disabling WiFi\r\n");
+        return false;
+    }
+#endif // IDW04A1
+
+    /*set idle mode (0->idle, 1->STA,3->miniAP, 2->IBSS)*/
+    if(!(_parser.send("AT+S.SCFG=wifi_mode,0") && _recv_ok()))
+    {
+        debug_if(_dbg_on, "\r\nSPWF> error wifi mode set idle (%d)\r\n", __LINE__);
+        return false;
+    }
+
+#if MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1
+    /*enable Wi-Fi device*/
+    if(!(_parser.send("AT+S.WIFI=1") && _recv_ok()))
+    {
+        debug_if(_dbg_on, "\r\nSPWF> error enabling WiFi\r\n");
+        return false;
+    }
+#endif // IDW04A1
+
+    // reset module
+    if(!reset()) {
+        debug_if(_dbg_on, "\r\nSPWF> SW reset failed (%s, %d)\r\n", __func__, __LINE__);
+        return false;
+    }
+
+    return true;
+}
+
+const char *SPWFSAxx::getIPAddress(void)
+{
+    unsigned int n1, n2, n3, n4;
+
+    if (!(_parser.send("AT+S.STS=ip_ipaddr")
+            && _parser.recv(SPWFXX_RECV_IP_ADDR, &n1, &n2, &n3, &n4)
+            && _recv_ok())) {
+        debug_if(_dbg_on, "\r\nSPWF> get IP address error\r\n");
+        return NULL;
+    }
+
+    debug_if(_dbg_on, "AT^ ip_ipaddr = %u.%u.%u.%u\r\n", n1, n2, n3, n4);
+
+    sprintf((char*)_ip_buffer,"%u.%u.%u.%u", n1, n2, n3, n4);
+    return _ip_buffer;
+}
+
+const char *SPWFSAxx::getGateway(void)
+{
+    unsigned int n1, n2, n3, n4;
+
+    if (!(_parser.send("AT+S.STS=ip_gw")
+            && _parser.recv(SPWFXX_RECV_GATEWAY, &n1, &n2, &n3, &n4)
+            && _recv_ok())) {
+        debug_if(_dbg_on, "\r\nSPWF> get gateway error\r\n");
+        return NULL;
+    }
+
+    debug_if(_dbg_on, "AT^ ip_gw = %u.%u.%u.%u\r\n", n1, n2, n3, n4);
+
+    sprintf((char*)_gateway_buffer,"%u.%u.%u.%u", n1, n2, n3, n4);
+    return _gateway_buffer;
+}
+
+const char *SPWFSAxx::getNetmask(void)
+{
+    unsigned int n1, n2, n3, n4;
+
+    if (!(_parser.send("AT+S.STS=ip_netmask")
+            && _parser.recv(SPWFXX_RECV_NETMASK, &n1, &n2, &n3, &n4)
+            && _recv_ok())) {
+        debug_if(_dbg_on, "\r\nSPWF> get netmask error\r\n");
+        return NULL;
+    }
+
+    debug_if(_dbg_on, "AT^ ip_netmask = %u.%u.%u.%u\r\n", n1, n2, n3, n4);
+
+    sprintf((char*)_netmask_buffer,"%u.%u.%u.%u", n1, n2, n3, n4);
+    return _netmask_buffer;
+}
+
+int8_t SPWFSAxx::getRssi(void)
+{
+    int ret;
+
+    if (!(_parser.send("AT+S.PEERS=0,rx_rssi")
+            && _parser.recv(SPWFXX_RECV_RX_RSSI, &ret)
+            && _recv_ok())) {
+        debug_if(_dbg_on, "\r\nSPWF> get RX rssi error\r\n");
+        return 0;
+    }
+
+    return (int8_t)ret;
+}
+
+const char *SPWFSAxx::getMACAddress(void)
+{
+    unsigned int n1, n2, n3, n4, n5, n6;
+
+    if (!(_parser.send("AT+S.GCFG=nv_wifi_macaddr")
+            && _parser.recv(SPWFXX_RECV_MAC_ADDR, &n1, &n2, &n3, &n4, &n5, &n6)
+            && _recv_ok())) {
+        debug_if(_dbg_on, "\r\nSPWF> get MAC address error\r\n");
+        return 0;
+    }
+
+    debug_if(_dbg_on, "AT^ nv_wifi_macaddr = %x:%x:%x:%x:%x:%x\r\n", n1, n2, n3, n4, n5, n6);
+
+    sprintf((char*)_mac_buffer,"%02X:%02X:%02X:%02X:%02X:%02X", n1, n2, n3, n4, n5, n6);
+    return _mac_buffer;
+}
+
+bool SPWFSAxx::isConnected(void)
+{
+    return _associated_interface._connected_to_network;
+}
+
+bool SPWFSAxx::send(int spwf_id, const void *data, uint32_t amount)
+{
+    uint32_t sent = 0U, to_send;
+    bool ret = true;
+
+    for(to_send = (amount > MBED_CONF_DRIVERS_UART_SERIAL_TXBUF_SIZE) ? MBED_CONF_DRIVERS_UART_SERIAL_TXBUF_SIZE : amount;
+            sent < amount;
+            to_send = ((amount - sent) > MBED_CONF_DRIVERS_UART_SERIAL_TXBUF_SIZE) ? MBED_CONF_DRIVERS_UART_SERIAL_TXBUF_SIZE : (amount - sent)) {
+        {
+            BH_HANDLER;
+
+            if (!(_parser.send("AT+S.SOCKW=%d,%d", spwf_id, (unsigned int)to_send)
+                    && (_parser.write(((char*)data)+sent, (int)to_send) == (int)to_send)
+                    && _recv_ok())) {
+                // betzw - TODO: handle different errors more accurately!
+                ret = false;
+                break;
+            }
+        }
+
+        sent += to_send;
+    }
+
+    return ret;
+}
+
+int SPWFSAxx::_read_len(int spwf_id) {
+    unsigned int amount;
+
+    if (!(_parser.send("AT+S.SOCKQ=%d", spwf_id)
+            && _parser.recv(SPWFXX_RECV_DATALEN, &amount)
+            && _recv_ok())) {
+        debug_if(_dbg_on, "\r\nSPWF> %s failed\r\n", __func__);
+        return 0;
+    }
+
+    return (int)amount;
+}
+
+#define SPWFXX_WINDS_OFF "0xFFFFFFFF"
+
+void SPWFSAxx::_winds_on(void) {
+    if(!(_parser.send(SPWFXX_SEND_WIND_OFF_HIGH SPWFXX_WINDS_HIGH_ON) && _recv_ok())) {
+    }
+    if(!(_parser.send(SPWFXX_SEND_WIND_OFF_MEDIUM SPWFXX_WINDS_MEDIUM_ON) && _recv_ok())) {
+    }
+    if(!(_parser.send(SPWFXX_SEND_WIND_OFF_LOW SPWFXX_WINDS_LOW_ON) && _recv_ok())) {
+    }
+}
+
+/* Note: in case of error blocking has been (tried to be) lifted */
+bool SPWFSAxx::_winds_off(void) {
+    if (!(_parser.send(SPWFXX_SEND_WIND_OFF_LOW SPWFXX_WINDS_OFF)
+            && _recv_ok())) {
+        _winds_on();
+        return false;
+    }
+
+    if (!(_parser.send(SPWFXX_SEND_WIND_OFF_MEDIUM SPWFXX_WINDS_OFF)
+            && _recv_ok())) {
+        _winds_on();
+        return false;
+    }
+
+    if (!(_parser.send(SPWFXX_SEND_WIND_OFF_HIGH SPWFXX_WINDS_OFF)
+            && _recv_ok())) {
+        _winds_on();
+        return false;
+    }
+
+    return true;
+}
+
+void SPWFSAxx::_execute_bottom_halves(void) {
+    _network_lost_handler_bh();
+    _packet_handler_bh();
+}
+
+void SPWFSAxx::_read_in_pending(void) {
+    static int internal_id_cnt = 0;
+
+    while(_is_data_pending()) {
+        int spwf_id = _associated_interface._ids[internal_id_cnt].spwf_id;
+
+        if(_associated_interface._socket_has_connected(internal_id_cnt)) {
+            if(_is_data_pending(spwf_id)) {
+                int amount;
+
+                amount = _read_in_packet(spwf_id);
+                if(amount < 0) {
+                    return; /* out of memory */
+                }
+            }
+
+            if(!_is_data_pending(spwf_id)) {
+                internal_id_cnt++;
+                internal_id_cnt %= SPWFSA_SOCKET_COUNT;
+            }
+        } else {
+            internal_id_cnt++;
+            internal_id_cnt %= SPWFSA_SOCKET_COUNT;
+        }
+    }
+}
+
+/* Note: returns
+ * '1'  in case of success
+ * '0'  in case of `_read_in()` error
+ * '-1' in case of "out of memory"
+ */
+int SPWFSAxx::_read_in_packet(int spwf_id, int amount) {
+    struct packet *packet = (struct packet*)malloc(sizeof(struct packet) + amount);
+    if (!packet) {
+#ifndef NDEBUG
+        error("%s(%d): Out of memory!", __func__, __LINE__);
+#else // NDEBUG
+        debug("%s(%d): Out of memory!", __func__, __LINE__);
+#endif
+        debug_if(_dbg_on, "\r\nSPWF> %s failed (%d)\r\n", __func__, __LINE__);
+        return -1; /* out of memory: give up here! */
+    }
+
+    /* init packet */
+    packet->id = spwf_id;
+    packet->len = (uint32_t)amount;
+    packet->next = 0;
+
+    /* read data in */
+    if(!(_read_in((char*)(packet + 1), spwf_id, (uint32_t)amount) > 0)) {
+        free(packet);
+        debug_if(_dbg_on, "\r\nSPWF> %s failed (%d)\r\n", __func__, __LINE__);
+        return 0;
+    } else {
+        /* append to packet list */
+        *_packets_end = packet;
+        _packets_end = &packet->next;
+
+        /* force call of (external) callback */
+        _call_callback();
+    }
+
+    return 1;
+}
+
+/* Note: returns
+ * '>0'  in case of success, amount of read in data (in bytes)
+ * '0'   in case of `_read_in()` error no more data to be read
+ * '-1'  in case of "out of memory"
+ */
+int SPWFSAxx::_read_in_packet(int spwf_id) {
+    int amount;
+    BlockExecuter netsock_wa_obj(Callback<void()>(this, &SPWFSAxx::_unblock_event_callback),
+                                 Callback<void()>(this, &SPWFSAxx::_block_event_callback)); /* call (external) callback only while not receiving */
+
+    _clear_pending_data(spwf_id);
+    amount = _read_len(spwf_id);
+    if(amount > 0) {
+        int ret = _read_in_packet(spwf_id, (uint32_t)amount);
+        if(ret <= 0) { /* "out of memory" or `_read_in()` error */
+            return ret;
+        }
+    }
+    return amount;
+}
+
+void SPWFSAxx::_free_packets(int spwf_id) {
+    // check if any packets are ready for `spwf_id`
+    for(struct packet **p = &_packets; *p;) {
+        if ((*p)->id == spwf_id) {
+            struct packet *q = *p;
+            if (_packets_end == &(*p)->next) {
+                _packets_end = p;
+            }
+            *p = (*p)->next;
+            free(q);
+        } else {
+            p = &(*p)->next;
+        }
+    }
+}
+
+void SPWFSAxx::_free_all_packets() {
+    for (int spwf_id = 0; spwf_id < SPWFSA_SOCKET_COUNT; spwf_id++) {
+        _free_packets(spwf_id);
+    }
+}
+
+/**
+ *	Recv Function
+ */
+int32_t SPWFSAxx::recv(int spwf_id, void *data, uint32_t amount)
+{
+    BH_HANDLER;
+
+    while (true) {
+        /* check if any packets are ready for us */
+        for (struct packet **p = &_packets; *p; p = &(*p)->next) {
+            if ((*p)->id == spwf_id) {
+                debug_if(_dbg_on, "\r\nRead done on ID %d and length of packet is %d\r\n",spwf_id,(*p)->len);
+                struct packet *q = *p;
+                if (q->len <= amount) { // Return and remove full packet
+                    memcpy(data, q+1, q->len);
+
+                    if (_packets_end == &(*p)->next) {
+                        _packets_end = p;
+                    }
+                    *p = (*p)->next;
+                    uint32_t len = q->len;
+                    free(q);
+                    return len;
+                }
+                else { // return only partial packet
+                    memcpy(data, q+1, amount);
+                    q->len -= amount;
+                    memmove(q+1, (uint8_t*)(q+1) + amount, q->len);
+                    return amount;
+                }
+            }
+        }
+
+        /* check for pending data on module */
+        {
+            int len;
+
+            len = _read_in_packet(spwf_id);
+            if(len <= 0)  { /* "out of memory", `_read_in()` error, or no more data to be read */
+                return -1;
+            }
+        }
+    }
+}
+
+#define CLOSE_MAX_RETRY (3)
+bool SPWFSAxx::close(int spwf_id)
+{
+    bool ret = false;
+    int retry_cnt = 0;
+
+    if(spwf_id == SPWFSA_SOCKET_COUNT) {
+        goto close_bh_handling;
+    }
+
+close_flush:
+    // Flush out pending data
+    while(true) {
+        int amount = _read_in_packet(spwf_id);
+        if(amount < 0) goto close_bh_handling; // out of memory
+        if(amount == 0) break; // no more data to be read or `_read_in()` error
+
+        /* immediately free packet (to avoid "out of memory") */
+        _free_packets(spwf_id);
+
+        /* interleave bottom halves */
+        _execute_bottom_halves();
+    }
+
+    // Close socket
+    if (_parser.send("AT+S.SOCKC=%d", spwf_id)
+            && _recv_ok()) {
+        ret = true;
+        goto close_bh_handling;
+    } else {
+        if(retry_cnt++ < CLOSE_MAX_RETRY) {
+            debug_if(_dbg_on, "\r\nSPWF> %s failed (%d)\r\n", __func__, __LINE__);
+            /* interleave bottom halves */
+            _execute_bottom_halves();
+
+            /* retry flushing (assuming data is still pending) */
+            goto close_flush;
+        }
+    }
+
+close_bh_handling:
+    /* anticipate bottom halves */
+    _execute_bottom_halves();
+
+    if(ret) {
+        /* clear pending data flag (should be redundant) */
+        _clear_pending_data(spwf_id);
+
+        /* free packets for this socket */
+        _free_packets(spwf_id);
+    } else {
+        debug_if(_dbg_on, "\r\nSPWF> SPWFSAxx::close failed (%d)\r\n", __LINE__);
+    }
+
+    return ret;
+}
+
+/*
+ * Buffered serial event handler
+ *
+ * Note: executed in IRQ context!
+ * Note: call (external) callback only while not receiving
+ */
+void SPWFSAxx::_event_handler(void)
+{
+    if(!_is_event_callback_blocked()) {
+        _call_callback();
+    }
+}
+
+/*
+ * Common error handler
+ */
+void SPWFSAxx::_error_handler(void)
+{
+    if(_parser.recv("%[^\n]\n", _err_msg_buffer) && _recv_delim_lf()) {
+        debug_if(_dbg_on, "AT^ ERROR:%s (%d)\r\n", _err_msg_buffer, __LINE__);
+    } else {
+        debug_if(_dbg_on, "\r\nSPWF> Unknown ERROR string in SPWFSAxx::_error_handler (%d)\r\n", __LINE__);
+    }
+
+    /* force call of (external) callback */
+    _call_callback();
+}
+
+/*
+ * Handling oob ("+WIND:33:WiFi Network Lost")
+ */
+void SPWFSAxx::_network_lost_handler_th(void)
+{
+#ifndef NDEBUG
+    static unsigned int net_loss_cnt = 0;
+    net_loss_cnt++;
+#endif
+
+    _recv_delim_cr_lf();
+
+    debug_if(_dbg_on, "AT^ +WIND:33:WiFi Network Lost\r\n");
+
+#ifndef NDEBUG
+    debug_if(_dbg_on, "Getting out of SPWFSAxx::_network_lost_handler_th: %d\r\n", net_loss_cnt);
+#else // NDEBUG
+    debug_if(_dbg_on, "Getting out of SPWFSAxx::_network_lost_handler_th: %d\r\n", __LINE__);
+#endif // NDEBUG
+
+    /* set flag to signal network loss */
+    _network_lost_flag = true;
+
+    return;
+}
+
+/*
+ * Handling oob ("+WIND:55:Pending Data")
+ */
+void SPWFSAxx::_packet_handler_th(void)
+{
+    int internal_id, spwf_id;
+    int amount;
+
+    /* parse out the socket id & amount */
+    if (!(_parser.recv(SPWFXX_RECV_PENDING_DATA, &spwf_id, &amount) && _recv_delim_lf())) {
+#ifndef NDEBUG
+        error("\r\nSPWFSAxx::%s failed!\r\n", __func__);
+#endif
+        return;
+    }
+
+    debug_if(_dbg_on, "AT^ +WIND:55:Pending Data:%d:%d\r\n", spwf_id, amount);
+
+    /* set that there is pending data for socket */
+    /* NOTE: it seems as if asynchronous indications might report not up-to-date data length values
+     *       therefore we just record the socket id without considering the `amount` of data reported!
+     */
+    internal_id = _associated_interface.get_internal_id(spwf_id);
+    if(internal_id != SPWFSA_SOCKET_COUNT) {
+        _set_pending_data(spwf_id);
+    } else {
+        debug_if(_dbg_on, "\r\nSPWFSAxx::%s got invalid id %d\r\n", __func__, spwf_id);
+    }
+}
+
+void SPWFSAxx::_network_lost_handler_bh(void)
+{
+    if(!_network_lost_flag) return;
+    _network_lost_flag = false;
+
+    {
+        bool were_connected;
+        BlockExecuter netsock_wa_obj(Callback<void()>(this, &SPWFSAxx::_unblock_and_callback),
+                                     Callback<void()>(this, &SPWFSAxx::_block_event_callback)); /* call (external) callback only while not receiving */
+        Timer timer;
+        timer.start();
+
+        _parser.set_timeout(SPWF_NETLOST_TIMEOUT);
+
+        were_connected = isConnected();
+        _associated_interface._connected_to_network = false;
+
+        if(were_connected) {
+            unsigned int n1, n2, n3, n4;
+
+            while(true) {
+                if (timer.read_ms() > SPWF_CONNECT_TIMEOUT) {
+                    debug_if(_dbg_on, "\r\nSPWFSAxx::_network_lost_handler_bh() #%d\r\n", __LINE__);
+                    disconnect();
+                    goto nlh_get_out;
+                }
+
+                if((_parser.recv(SPWFXX_RECV_WIFI_UP, &n1, &n2, &n3, &n4)) && _recv_delim_lf()) {
+                    debug_if(_dbg_on, "Re-connected (%u.%u.%u.%u)!\r\n", n1, n2, n3, n4);
+
+                    _associated_interface._connected_to_network = true;
+                    goto nlh_get_out;
+                }
+            }
+        } else {
+            debug_if(_dbg_on, "Leaving SPWFSAxx::_network_lost_handler_bh\r\n");
+            goto nlh_get_out;
+        }
+
+    nlh_get_out:
+        debug_if(_dbg_on, "Getting out of SPWFSAxx::_network_lost_handler_bh\r\n");
+        _parser.set_timeout(_timeout);
+
+        return;
+    }
+}
+
+void SPWFSAxx::_recover_from_hard_faults(void) {
+    disconnect();
+    _associated_interface.inner_constructor();
+    _free_all_packets();
+    empty_rx_buffer();
+
+    /* force call of (external) callback */
+    _call_callback();
+}
+
+/*
+ * Handling oob ("+WIND:8:Hard Fault")
+ */
+void SPWFSAxx::_hard_fault_handler(void)
+{
+    _parser.set_timeout(SPWF_RECV_TIMEOUT);
+    if(_parser.recv("%[^\n]\n", _err_msg_buffer) && _recv_delim_lf()) {}
+
+#ifndef NDEBUG
+    error("\r\nSPWFSAXX hard fault error:\r\n%s\r\n", _err_msg_buffer);
+#else // NDEBUG
+    debug("\r\nSPWFSAXX hard fault error:\r\n%s\r\n", _err_msg_buffer);
+
+    // This is most likely the best we can do to recover from this module hard fault
+    _parser.set_timeout(SPWF_HF_TIMEOUT);
+    _recover_from_hard_faults();
+    _parser.set_timeout(_timeout);
+#endif // NDEBUG
+
+    /* force call of (external) callback */
+    _call_callback();
+}
+
+/*
+ * Handling oob ("+WIND:5:WiFi Hardware Failure")
+ */
+void SPWFSAxx::_wifi_hwfault_handler(void)
+{
+    unsigned int failure_nr;
+
+    /* parse out the socket id & amount */
+    _parser.recv(":%u\n", &failure_nr);
+    _recv_delim_lf();
+
+#ifndef NDEBUG
+    error("\r\nSPWFSAXX wifi HW fault error: %u\r\n", failure_nr);
+#else // NDEBUG
+    debug("\r\nSPWFSAXX wifi HW fault error: %u\r\n", failure_nr);
+
+    // This is most likely the best we can do to recover from this module hard fault
+    _parser.set_timeout(SPWF_HF_TIMEOUT);
+    _recover_from_hard_faults();
+    _parser.set_timeout(_timeout);
+#endif // NDEBUG
+
+    /* force call of (external) callback */
+    _call_callback();
+}
+
+/*
+ * Handling oob ("+WIND:58:Socket Closed")
+ * when server closes a client connection
+ *
+ * NOTE: When a socket client receives an indication about socket server gone (only for TCP sockets, WIND:58),
+ *       the socket connection is NOT automatically closed!
+ */
+void SPWFSAxx::_server_gone_handler(void)
+{
+    int spwf_id, internal_id;
+
+    if(!(_parser.recv(SPWFXX_RECV_SOCKET_CLOSED, &spwf_id) && _recv_delim_lf())) {
+#ifndef NDEBUG
+        error("\r\nSPWFSAxx::%s failed!\r\n", __func__);
+#endif
+        goto _get_out;
+    }
+
+    debug_if(_dbg_on, "AT^ +WIND:58:Socket Closed:%d\r\n", spwf_id);
+
+    /* check for the module to report a valid id */
+    MBED_ASSERT(((unsigned int)spwf_id) < ((unsigned int)SPWFSA_SOCKET_COUNT));
+
+    /* only set `server_gone`
+     * user still can receive date & must still explicitly close the socket
+     */
+    internal_id = _associated_interface.get_internal_id(spwf_id);
+    if(internal_id != SPWFSA_SOCKET_COUNT) {
+        _associated_interface._ids[internal_id].server_gone = true;
+    }
+
+_get_out:
+    /* force call of (external) callback */
+    _call_callback();
+}
+
+void SPWFSAxx::setTimeout(uint32_t timeout_ms)
+{
+    _timeout = timeout_ms;
+    _parser.set_timeout(timeout_ms);
+}
+
+void SPWFSAxx::attach(Callback<void()> func)
+{
+    _callback_func = func; /* call (external) callback only while not receiving */
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-x-nucleo-idw01m1/SPWFSAxx.h	Wed Oct 28 07:42:46 2020 +0000
@@ -0,0 +1,345 @@
+/* SPWFSAxx Devices
+ * Copyright (c) 2015 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+#ifndef SPWFSAXX_H
+#define SPWFSAXX_H
+
+#include "mbed.h"
+#include "ATCmdParser.h"
+#include "BlockExecuter.h"
+
+/* Common SPWFSAxx macros */
+#define SPWFXX_WINDS_LOW_ON         "0x00000000"
+#define SPWFXX_DEFAULT_BAUD_RATE    115200
+#define SPWFXX_MAX_TRIALS           100
+
+#if !defined(SPWFSAXX_RTS_PIN)
+#define SPWFSAXX_RTS_PIN    NC
+#endif // !defined(SPWFSAXX_RTS_PIN)
+#if !defined(SPWFSAXX_CTS_PIN)
+#define SPWFSAXX_CTS_PIN    NC
+#endif // !defined(SPWFSAXX_CTS_PIN)
+
+class SpwfSAInterface;
+
+/** SPWFSAxx Interface class.
+    This is an interface to a SPWFSAxx module.
+ */
+class SPWFSAxx
+{
+private:
+    /* abstract class*/
+    SPWFSAxx(PinName tx, PinName rx, PinName rts, PinName cts,
+             SpwfSAInterface &ifce, bool debug,
+             PinName wakeup, PinName reset);
+
+public:
+    /**
+     * Init the SPWFSAxx
+     *
+     * @param mode mode in which to startup
+     * @return true only if SPWFSAxx has started up correctly
+     */
+    bool startup(int mode);
+
+    /**
+     * Connect SPWFSAxx to AP
+     *
+     * @param ap the name of the AP
+     * @param passPhrase the password of AP
+     * @param securityMode the security mode of AP (WPA/WPA2, WEP, Open)
+     * @return true only if SPWFSAxx is connected successfully
+     */
+    bool connect(const char *ap, const char *passPhrase, int securityMode);
+
+    /**
+     * Disconnect SPWFSAxx from AP
+     *
+     * @return true only if SPWFSAxx is disconnected successfully
+     */
+    bool disconnect(void);
+
+    /**
+     * Get the IP address of SPWFSAxx
+     *
+     * @return null-teriminated IP address or null if no IP address is assigned
+     */
+    const char *getIPAddress(void);
+
+    /**
+     * Get the MAC address of SPWFSAxx
+     *
+     * @return null-terminated MAC address or null if no MAC address is assigned
+     */
+    const char *getMACAddress(void);
+
+    /** Get the local gateway
+     *
+     *  @return         Null-terminated representation of the local gateway
+     *                  or null if no network mask has been recieved
+     */
+    const char *getGateway(void);
+
+    /** Get the local network mask
+     *
+     *  @return         Null-terminated representation of the local network mask
+     *                  or null if no network mask has been recieved
+     */
+    const char *getNetmask(void);
+
+    /** Gets the current radio signal strength for active connection
+     *
+     * @return          Connection strength in dBm (negative value)
+     */
+    int8_t getRssi();
+
+    /**
+     * Sends data to an open socket
+     *
+     * @param id id of socket to send to
+     * @param data data to be sent
+     * @param amount amount of data to be sent - max 1024
+     * @return true only if data sent successfully
+     */
+    bool send(int id, const void *data, uint32_t amount);
+
+    /**
+     * Receives data from an open socket
+     *
+     * @param id id to receive from
+     * @param data placeholder for returned information
+     * @param amount number of bytes to be received
+     * @return the number of bytes received
+     */
+    int32_t recv(int id, void *data, uint32_t amount);
+
+    /**
+     * Closes a socket
+     *
+     * @param id id of socket to close, valid only 0-4
+     * @return true only if socket is closed successfully
+     */
+    bool close(int id);
+
+    /**
+     * Allows timeout to be changed between commands
+     *
+     * @param timeout_ms timeout of the connection
+     */
+    void setTimeout(uint32_t timeout_ms);
+
+    /**
+     * Attach a function to call whenever network state has changed
+     *
+     * @param func A pointer to a void function, or 0 to set as none
+     */
+    void attach(Callback<void()> func);
+
+    /**
+     * Attach a function to call whenever network state has changed
+     *
+     * @param obj pointer to the object to call the member function on
+     * @param method pointer to the member function to call
+     */
+    template <typename T, typename M>
+    void attach(T *obj, M method) {
+        attach(Callback<void()>(obj, method));
+    }
+
+    static const char _cr_ = '\x0d'; // '\r' carriage return
+    static const char _lf_ = '\x0a'; // '\n' line feed
+
+private:
+    UARTSerial _serial;
+    ATCmdParser _parser;
+    DigitalOut _wakeup;
+    DigitalOut _reset;
+    PinName _rts;
+    PinName _cts;
+    int _timeout;
+    bool _dbg_on;
+    int _pending_sockets_bitmap;
+    bool _network_lost_flag;
+    SpwfSAInterface &_associated_interface;
+
+    /**
+     * Reset SPWFSAxx
+     *
+     * @return true only if SPWFSAxx resets successfully
+     */
+    bool hw_reset(void);
+    bool reset(void);
+
+    /**
+     * Check if SPWFSAxx is connected
+     *
+     * @return true only if the chip has an IP address
+     */
+    bool isConnected(void);
+
+    /**
+     * Checks if data is available
+     */
+    bool readable(void) {
+        return _serial.FileHandle::readable();
+    }
+
+    /**
+     * Checks if data can be written
+     */
+    bool writeable(void) {
+        return _serial.FileHandle::writable();
+    }
+
+    /**
+     * Try to empty RX buffer
+     * Can be used when commands fail receiving expected response to try to recover situation
+     * @note Gives no guarantee that situation improves
+     */
+    void empty_rx_buffer(void) {
+        while(readable()) _parser.getc();
+    }
+
+    /* call (external) callback only while not receiving */
+    volatile bool _call_event_callback_blocked;
+    Callback<void()> _callback_func;
+
+    struct packet {
+        struct packet *next;
+        int id;
+        uint32_t len;
+        // data follows
+    } *_packets, **_packets_end;
+
+    void _packet_handler_th(void);
+    void _execute_bottom_halves(void);
+    void _network_lost_handler_th(void);
+    void _network_lost_handler_bh(void);
+    void _hard_fault_handler(void);
+    void _wifi_hwfault_handler(void);
+    void _server_gone_handler(void);
+    bool _wait_wifi_hw_started(void);
+    bool _wait_console_active(void);
+    int _read_len(int);
+    int _flush_in(char*, int);
+    bool _winds_off(void);
+    void _winds_on(void);
+    void _read_in_pending(void);
+    int _read_in_packet(int spwf_id);
+    int _read_in_packet(int spwf_id, int amount);
+    void _recover_from_hard_faults(void);
+    void _free_packets(int spwf_id);
+    void _free_all_packets(void);
+
+    virtual int _read_in(char*, int, uint32_t) = 0;
+
+    bool _recv_delim_lf(void) {
+        return (_parser.getc() == _lf_);
+    }
+
+    bool _recv_delim_cr(void) {
+        return (_parser.getc() == _cr_);
+    }
+
+    bool _recv_delim_cr_lf(void) {
+        return _recv_delim_cr() && _recv_delim_lf();
+    }
+
+    bool _recv_ok(void) {
+        return _parser.recv(SPWFXX_RECV_OK) && _recv_delim_lf();
+    }
+
+    bool _is_data_pending(void) {
+        if(_pending_sockets_bitmap != 0) return true;
+        else return false;
+    }
+
+    void _set_pending_data(int spwf_id) {
+        _pending_sockets_bitmap |= (1 << spwf_id);
+    }
+
+    void _clear_pending_data(int spwf_id) {
+        _pending_sockets_bitmap &= ~(1 << spwf_id);
+    }
+
+    bool _is_data_pending(int spwf_id) {
+        return (_pending_sockets_bitmap & (1 << spwf_id)) ? true : false;
+    }
+
+    void _packet_handler_bh(void) {
+        /* read in other eventually pending packages */
+        _read_in_pending();
+    }
+
+    /* call (external) callback only while not receiving */
+    void _event_handler(void);
+
+    void _error_handler(void);
+
+    void _call_callback(void) {
+        if((bool)_callback_func) {
+            _callback_func();
+        }
+    }
+
+    bool _is_event_callback_blocked(void) {
+        return _call_event_callback_blocked;
+    }
+
+    void _block_event_callback(void) {
+        MBED_ASSERT(!_call_event_callback_blocked);
+        _call_event_callback_blocked = true;
+    }
+
+    void _unblock_event_callback(void) {
+        MBED_ASSERT(_call_event_callback_blocked);
+        _call_event_callback_blocked = false;
+        _trigger_event_callback();
+    }
+
+    /* unblock & force call of (external) callback */
+    void _unblock_and_callback(void) {
+        MBED_ASSERT(_call_event_callback_blocked);
+        _call_event_callback_blocked = false;
+        _call_callback();
+    }
+
+    /* trigger call of (external) callback in case there is still data */
+    void _trigger_event_callback(void) {
+        MBED_ASSERT(!_call_event_callback_blocked);
+        /* if still data available */
+        if(readable()) {
+            _call_callback();
+        }
+    }
+
+    char _ip_buffer[16];
+    char _gateway_buffer[16];
+    char _netmask_buffer[16];
+    char _mac_buffer[18];
+
+    char ssid_buf[256]; /* required to handle not 802.11 compliant ssid's */
+    char *_err_msg_buffer;
+
+private:
+    friend class SPWFSA01;
+    friend class SPWFSA04;
+};
+
+#define BH_HANDLER \
+        BlockExecuter bh_handler(Callback<void()>(this, &SPWFSAxx::_execute_bottom_halves))
+
+#endif // SPWFSAXX_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-x-nucleo-idw01m1/SpwfSAInterface.cpp	Wed Oct 28 07:42:46 2020 +0000
@@ -0,0 +1,495 @@
+/* mbed Microcontroller Library
+* Copyright (c) 20015 ARM Limited
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/**
+  ******************************************************************************
+  * @file    SpwfSAInterface.cpp
+  * @author  STMicroelectronics
+  * @brief   Implementation of the NetworkStack for the SPWF Device
+  ******************************************************************************
+  * @copy
+  *
+  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
+  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
+  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
+  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
+  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+  *
+  * <h2><center>&copy; COPYRIGHT 2016 STMicroelectronics</center></h2>
+  ******************************************************************************
+  */
+
+#include "SpwfSAInterface.h"
+#include "mbed_debug.h"
+
+/**
+ * @brief  SpwfSAInterface constructor
+ * @param  tx: Pin USART TX
+ *         rx: Pin USART RX
+ *         rts: Pin USART RTS
+ *         cts: Pin USART RTS
+ *         debug : not used
+ * @retval none
+ */
+SpwfSAInterface::SpwfSAInterface(PinName tx, PinName rx,
+                                 PinName rts, PinName cts, bool debug,
+                                 PinName wakeup, PinName reset)
+: _spwf(tx, rx, rts, cts, *this, debug, wakeup, reset),
+  _dbg_on(debug)
+{
+    inner_constructor();
+}
+
+/**
+ * @brief  init function
+ *         initializes SPWF FW and module
+ * @param  none
+ * @retval error value
+ */
+nsapi_error_t SpwfSAInterface::init(void)
+{
+    _spwf.setTimeout(SPWF_INIT_TIMEOUT);
+
+    if(_spwf.startup(0)) {
+        return NSAPI_ERROR_OK;
+    }
+    else return NSAPI_ERROR_DEVICE_ERROR;
+}
+
+nsapi_error_t SpwfSAInterface::connect(void)
+{
+    int mode;
+    char *pass_phrase = ap_pass;
+
+    switch(ap_sec)
+    {
+        case NSAPI_SECURITY_NONE:
+            mode = 0;
+            pass_phrase = NULL;
+            break;
+        case NSAPI_SECURITY_WEP:
+            mode = 1;
+            break;
+        case NSAPI_SECURITY_WPA:
+        case NSAPI_SECURITY_WPA2:
+            mode = 2;
+            break;
+        default:
+            mode = 2;
+            break;
+    }
+
+    // First: disconnect
+    if(_connected_to_network) {
+        if(!disconnect()) {
+            return NSAPI_ERROR_DEVICE_ERROR;
+        }
+    }
+
+    //initialize the device before connecting
+    if(!_isInitialized)
+    {
+        if(init() != NSAPI_ERROR_OK) return NSAPI_ERROR_DEVICE_ERROR;
+        _isInitialized=true;
+    }
+
+    // Then: (re-)connect
+    _spwf.setTimeout(SPWF_CONNECT_TIMEOUT);
+
+    if (!_spwf.connect(ap_ssid, pass_phrase, mode)) {
+        return NSAPI_ERROR_NO_CONNECTION;
+    }
+
+    if (!_spwf.getIPAddress()) {
+        return NSAPI_ERROR_DHCP_FAILURE;
+    }
+
+    _connected_to_network = true;
+    return NSAPI_ERROR_OK;
+}
+
+/**
+ * @brief  network connect
+ *         connects to Access Point
+ * @param  ap: Access Point (AP) Name String
+ *         pass_phrase: Password String for AP
+ *         security: type of NSAPI security supported
+ * @retval NSAPI Error Type
+ */
+nsapi_error_t SpwfSAInterface::connect(const char *ssid, const char *pass, nsapi_security_t security,
+                                       uint8_t channel)
+{
+    if (channel != 0) {
+        return NSAPI_ERROR_UNSUPPORTED;
+    }
+
+    set_credentials(ssid, pass, security);
+    return connect();
+}
+
+/**
+ * @brief  network disconnect
+ *         disconnects from Access Point
+ * @param  none
+ * @retval NSAPI Error Type
+ */
+nsapi_error_t SpwfSAInterface::disconnect(void)
+{
+    _spwf.setTimeout(SPWF_DISCONNECT_TIMEOUT);
+
+    if (!_spwf.disconnect()) {
+        return NSAPI_ERROR_DEVICE_ERROR;
+    }
+
+    _connected_to_network = false;
+    _isInitialized = false;
+
+    return NSAPI_ERROR_OK;
+}
+
+/** 
+ * @brief  Get the local IP address
+ * @param  none
+ * @retval Null-terminated representation of the local IP address
+ *         or null if not yet connected
+ */
+const char *SpwfSAInterface::get_ip_address(void)
+{
+    _spwf.setTimeout(SPWF_MISC_TIMEOUT);
+    return _spwf.getIPAddress();
+}
+
+/** 
+ * @brief  Get the MAC address
+ * @param  none
+ * @retval Null-terminated representation of the MAC address
+ *         or null if not yet connected
+ */
+const char *SpwfSAInterface::get_mac_address(void)
+{
+    _spwf.setTimeout(SPWF_MISC_TIMEOUT);
+    return _spwf.getMACAddress();
+}
+
+const char *SpwfSAInterface::get_gateway(void)
+{
+    if(!_connected_to_network) return NULL;
+
+    _spwf.setTimeout(SPWF_MISC_TIMEOUT);
+    return _spwf.getGateway();
+}
+
+const char *SpwfSAInterface::get_netmask(void)
+{
+    if(!_connected_to_network) return NULL;
+
+    _spwf.setTimeout(SPWF_MISC_TIMEOUT);
+    return _spwf.getNetmask();
+}
+
+/**
+ * @brief  open a socket handle
+ * @param  handle: Pointer to handle
+ *         proto: TCP/UDP protocol
+ * @retval NSAPI Error Type
+ */
+nsapi_error_t SpwfSAInterface::socket_open(void **handle, nsapi_protocol_t proto)
+{
+    int internal_id;
+
+    for (internal_id = 0; internal_id < SPWFSA_SOCKET_COUNT; internal_id++) {
+        if (_ids[internal_id].internal_id == SPWFSA_SOCKET_COUNT) break;
+    }
+
+    if(internal_id == SPWFSA_SOCKET_COUNT) {
+        debug_if(_dbg_on, "NO Socket ID Error\r\n");
+        return NSAPI_ERROR_NO_SOCKET;
+    }
+
+    spwf_socket_t *socket = &_ids[internal_id];
+    socket->internal_id = internal_id;
+    socket->spwf_id = SPWFSA_SOCKET_COUNT;
+    socket->server_gone = false;
+    socket->no_more_data = false;
+    socket->proto = proto;
+    socket->addr = SocketAddress();
+
+    *handle = socket;
+    return NSAPI_ERROR_OK;
+}
+
+/**
+ * @brief  connect to a remote socket
+ * @param  handle: Pointer to socket handle
+ *         addr: Address to connect to
+ * @retval NSAPI Error Type
+ */
+nsapi_error_t SpwfSAInterface::socket_connect(void *handle, const SocketAddress &addr)
+{
+    spwf_socket_t *socket = (spwf_socket_t*)handle;
+
+    MBED_ASSERT(socket->internal_id != SPWFSA_SOCKET_COUNT);
+
+    if(_socket_has_connected(socket->internal_id)) return NSAPI_ERROR_IS_CONNECTED;
+
+    _spwf.setTimeout(SPWF_OPEN_TIMEOUT);
+
+    const char *proto = (socket->proto == NSAPI_UDP) ? "u" : "t"; //"s" for secure socket?
+
+    if(addr.get_ip_version() != NSAPI_IPv4) { // IPv6 not supported (yet)
+        return NSAPI_ERROR_UNSUPPORTED;
+    }
+
+    if(!_spwf.open(proto, &socket->spwf_id, addr.get_ip_address(), addr.get_port())) {
+        return NSAPI_ERROR_DEVICE_ERROR;
+    }
+
+    /* check for the module to report a valid id */
+    MBED_ASSERT(((unsigned int)socket->spwf_id) < ((unsigned int)SPWFSA_SOCKET_COUNT));
+
+    _internal_ids[socket->spwf_id] = socket->internal_id;
+    socket->addr = addr;
+    return NSAPI_ERROR_OK;
+}
+
+nsapi_error_t SpwfSAInterface::socket_bind(void *handle, const SocketAddress &address)
+{
+    return NSAPI_ERROR_UNSUPPORTED;
+}
+
+nsapi_error_t SpwfSAInterface::socket_listen(void *handle, int backlog)
+{      
+    return NSAPI_ERROR_UNSUPPORTED;
+}
+
+nsapi_error_t SpwfSAInterface::socket_accept(nsapi_socket_t server, nsapi_socket_t *handle, SocketAddress *address)
+{    
+    return NSAPI_ERROR_UNSUPPORTED;
+}
+
+nsapi_error_t SpwfSAInterface::socket_close(void *handle)
+{
+    spwf_socket_t *socket = (spwf_socket_t*)handle;
+    int internal_id = socket->internal_id;
+
+    if(!_socket_is_open(internal_id)) return NSAPI_ERROR_NO_SOCKET;
+
+    if(this->_socket_has_connected(socket)) {
+        _spwf.setTimeout(SPWF_CLOSE_TIMEOUT);
+        if (!_spwf.close(socket->spwf_id)) {
+            return NSAPI_ERROR_DEVICE_ERROR;
+        }
+        _internal_ids[socket->spwf_id] = SPWFSA_SOCKET_COUNT;
+    }
+
+    _ids[internal_id].internal_id = SPWFSA_SOCKET_COUNT;
+    _ids[internal_id].spwf_id = SPWFSA_SOCKET_COUNT;
+
+    return NSAPI_ERROR_OK;
+}
+
+/**
+ * @brief  write to a socket
+ * @param  handle: Pointer to handle
+ *         data: pointer to data
+ *         size: size of data
+ * @retval no of bytes sent
+ */
+nsapi_size_or_error_t SpwfSAInterface::socket_send(void *handle, const void *data, unsigned size)
+{
+    spwf_socket_t *socket = (spwf_socket_t*)handle;
+
+    CHECK_NOT_CONNECTED_ERR();
+
+    _spwf.setTimeout(SPWF_SEND_TIMEOUT);
+
+    if(!_socket_is_still_connected(socket)) {
+        return NSAPI_ERROR_CONNECTION_LOST;
+    }
+
+    if (!_spwf.send(socket->spwf_id, data, size)) {
+        return NSAPI_ERROR_DEVICE_ERROR;
+    }
+
+    return size;
+}
+
+/**
+ * @brief  receive data on a socket
+ * @param  handle: Pointer to handle
+ *         data: pointer to data
+ *         size: size of data
+ * @retval no of bytes read or negative error code in case of error
+ */
+nsapi_size_or_error_t SpwfSAInterface::socket_recv(void *handle, void *data, unsigned size)
+{
+    spwf_socket_t *socket = (spwf_socket_t*)handle;
+
+    CHECK_NOT_CONNECTED_ERR();
+
+    if(!_socket_might_have_data(socket)) {
+        return NSAPI_ERROR_CONNECTION_LOST;
+    }
+
+    _spwf.setTimeout(SPWF_RECV_TIMEOUT);
+
+    int32_t recv = _spwf.recv(socket->spwf_id, (char*)data, (uint32_t)size);
+
+    MBED_ASSERT((recv != 0) || (size == 0));
+
+    if (recv < 0) {
+        if(!_socket_is_still_connected(socket)) {
+            socket->no_more_data = true;
+            return NSAPI_ERROR_CONNECTION_LOST;
+        }
+
+        return NSAPI_ERROR_WOULD_BLOCK;
+    }
+
+    return recv;
+}
+
+/**
+ * @brief  send data to a udp socket
+ * @param  handle: Pointer to handle
+ *         addr: address of udp socket
+ *         data: pointer to data
+ *         size: size of data
+ * @retval no of bytes sent
+ */
+nsapi_size_or_error_t SpwfSAInterface::socket_sendto(void *handle, const SocketAddress &addr, const void *data, unsigned size)
+{
+    spwf_socket_t *socket = (spwf_socket_t*)handle;
+
+    CHECK_NOT_CONNECTED_ERR();
+
+    if ((this->_socket_has_connected(socket)) && (socket->addr != addr)) {
+        _spwf.setTimeout(SPWF_CLOSE_TIMEOUT);
+        if (!_spwf.close(socket->spwf_id)) {
+            return NSAPI_ERROR_DEVICE_ERROR;
+        }
+        _internal_ids[socket->spwf_id] = SPWFSA_SOCKET_COUNT;
+        socket->spwf_id = SPWFSA_SOCKET_COUNT;
+    }
+
+    _spwf.setTimeout(SPWF_CONN_SND_TIMEOUT);
+    if (!this->_socket_has_connected(socket)) {
+        nsapi_error_t err = socket_connect(socket, addr);
+        if (err < 0) {
+            return err;
+        }
+    }
+
+    return socket_send(socket, data, size);
+}
+
+/**
+ * @brief  receive data on a udp socket
+ * @param  handle: Pointer to handle
+ *         addr: address of udp socket
+ *         data: pointer to data
+ *         size: size of data
+ * @retval no of bytes read
+ */
+nsapi_size_or_error_t SpwfSAInterface::socket_recvfrom(void *handle, SocketAddress *addr, void *data, unsigned size)
+{
+    spwf_socket_t *socket = (spwf_socket_t*)handle;
+    nsapi_error_t ret;
+
+    CHECK_NOT_CONNECTED_ERR();
+
+    ret = socket_recv(socket, data, size);
+    if (ret >= 0 && addr) {
+        *addr = socket->addr;
+    }
+
+    return ret;
+}
+
+/**
+ * @brief  attach function/callback to the socket
+ * @param  handle: Pointer to handle
+ *         callback: callback function pointer
+ *         data: pointer to data
+ * @retval none
+ */
+void SpwfSAInterface::socket_attach(void *handle, void (*callback)(void *), void *data)
+{
+    spwf_socket_t *socket = (spwf_socket_t*)handle;
+
+    if(!_socket_is_open(socket)) return; // might happen after module hard fault
+
+    _cbs[socket->internal_id].callback = callback;
+    _cbs[socket->internal_id].data = data;
+}
+
+void SpwfSAInterface::event(void) {
+    for (int internal_id = 0; internal_id < SPWFSA_SOCKET_COUNT; internal_id++) {
+        if (_cbs[internal_id].callback && (_ids[internal_id].internal_id != SPWFSA_SOCKET_COUNT)) {
+            _cbs[internal_id].callback(_cbs[internal_id].data);
+        }
+    }
+}
+
+nsapi_error_t SpwfSAInterface::set_credentials(const char *ssid, const char *pass, nsapi_security_t security)
+{
+    memset(ap_ssid, 0, sizeof(ap_ssid));
+    strncpy(ap_ssid, ssid, sizeof(ap_ssid));
+
+    memset(ap_pass, 0, sizeof(ap_pass));
+    strncpy(ap_pass, pass, sizeof(ap_pass));
+
+    ap_sec = security;
+
+    return NSAPI_ERROR_OK;
+}
+
+nsapi_error_t SpwfSAInterface::set_channel(uint8_t channel)
+{
+    return NSAPI_ERROR_UNSUPPORTED;
+}
+
+int8_t SpwfSAInterface::get_rssi(void)
+{
+    if(!_connected_to_network) return 0;
+
+    _spwf.setTimeout(SPWF_MISC_TIMEOUT);
+    return _spwf.getRssi();
+}
+
+nsapi_size_or_error_t SpwfSAInterface::scan(WiFiAccessPoint *res, unsigned count)
+{
+    nsapi_size_or_error_t ret;
+
+    //initialize the device before scanning
+    if(!_isInitialized)
+    {
+        if(init() != NSAPI_ERROR_OK) return NSAPI_ERROR_DEVICE_ERROR;
+    }
+
+    _spwf.setTimeout(SPWF_SCAN_TIMEOUT);
+    ret = _spwf.scan(res, count);
+
+    //de-initialize the device after scanning
+    if(!_isInitialized)
+    {
+        nsapi_error_t err = disconnect();
+        if(err != NSAPI_ERROR_OK) return err;
+    }
+
+    return ret;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-x-nucleo-idw01m1/SpwfSAInterface.h	Wed Oct 28 07:42:46 2020 +0000
@@ -0,0 +1,443 @@
+/* mbed Microcontroller Library
+* Copyright (c) 2015 ARM Limited
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/**
+  ******************************************************************************
+  * @file    SpwfSAInterface.h
+  * @author  STMicroelectronics
+  * @brief   Header file of the NetworkStack for the SPWF Device
+  ******************************************************************************
+  * @copy
+  *
+  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
+  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
+  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
+  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
+  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+  *
+  * <h2><center>&copy; COPYRIGHT 2016 STMicroelectronics</center></h2>
+  ******************************************************************************
+  */
+  
+#ifndef SPWFSA_INTERFACE_H
+#define SPWFSA_INTERFACE_H
+
+#include <limits.h>
+
+#include "mbed.h"
+
+#define IDW01M1 1
+#define IDW04A1 2
+
+#if MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW01M1
+#include "SPWFSA01/SPWFSA01.h"
+#elif MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1
+#include "SPWFSA04/SPWFSA04.h"
+#else
+#error No (valid) Wi-Fi exapnsion board defined (MBED_CONF_IDW0XX1_EXPANSION_BOARD: options are IDW01M1 and IDW04A1)
+#endif
+
+/* Max number of sockets */
+#define SPWFSA_SOCKET_COUNT 8
+
+// Various timeouts for different SPWF operations
+#define SPWF_CONNECT_TIMEOUT    60000
+#define SPWF_DISCONNECT_TIMEOUT 30002
+#define SPWF_HF_TIMEOUT         30001
+#define SPWF_NETLOST_TIMEOUT    30000
+#define SPWF_READ_BIN_TIMEOUT   13000
+#define SPWF_SEND_TIMEOUT       10000
+#define SPWF_INIT_TIMEOUT       8000
+#define SPWF_CLOSE_TIMEOUT      5003
+#define SPWF_OPEN_TIMEOUT       5002
+#define SPWF_CONN_SND_TIMEOUT   5001
+#define SPWF_SCAN_TIMEOUT       5000
+#define SPWF_MISC_TIMEOUT       301
+#define SPWF_RECV_TIMEOUT       300
+
+/** SpwfSAInterface class
+ *  Implementation of the NetworkStack for the SPWF Device
+ *  NOTE - betzw - TODO: MUST become singleton!
+ */
+class SpwfSAInterface : public NetworkStack, public WiFiInterface
+{
+public:
+    /** SpwfSAInterface constructor
+     * @param tx        TX pin
+     * @param rx        RX pin
+     * @param rts       RTS pin
+     * @param cts       CTS pin
+     * @param debug     Enable debugging
+     * @param wakeup    Wakeup pin
+     * @param reset     Reset pin
+     */
+    SpwfSAInterface(PinName tx, PinName rx,
+                    PinName rts = SPWFSAXX_RTS_PIN, PinName cts = SPWFSAXX_CTS_PIN, bool debug = false,
+                    PinName wakeup = SPWFSAXX_WAKEUP_PIN, PinName reset = SPWFSAXX_RESET_PIN);
+
+    /** Start the interface
+     *
+     *  Attempts to connect to a WiFi network. Requires ssid and passphrase to be set.
+     *  If passphrase is invalid, NSAPI_ERROR_AUTH_ERROR is returned.
+     *
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual nsapi_error_t connect();
+
+    /** Start the interface
+     *
+     *  Attempts to connect to a WiFi network.
+     *
+     *  @param ssid      Name of the network to connect to
+     *  @param pass      Security passphrase to connect to the network
+     *  @param security  Type of encryption for connection (Default: NSAPI_SECURITY_NONE)
+     *  @param channel   This parameter is not supported, setting it to anything else than 0 will result in NSAPI_ERROR_UNSUPPORTED
+     *  @return          0 on success, or error code on failure
+     */
+    virtual nsapi_error_t connect(const char *ssid, const char *pass, nsapi_security_t security = NSAPI_SECURITY_NONE,
+                                  uint8_t channel = 0);
+
+    /** Set the WiFi network credentials
+     *
+     *  @param ssid      Name of the network to connect to
+     *  @param pass      Security passphrase to connect to the network
+     *  @param security  Type of encryption for connection
+     *                   (defaults to NSAPI_SECURITY_NONE)
+     *  @return          0 on success, or error code on failure
+     */
+    virtual nsapi_error_t set_credentials(const char *ssid, const char *pass, nsapi_security_t security = NSAPI_SECURITY_NONE);
+
+    /** Set the WiFi network channel - NOT SUPPORTED
+     *
+     *  This function is not supported and will return NSAPI_ERROR_UNSUPPORTED
+     *
+     *  @param channel   Channel on which the connection is to be made, or 0 for any (Default: 0)
+     *  @return          Not supported, returns NSAPI_ERROR_UNSUPPORTED
+     */
+    virtual nsapi_error_t set_channel(uint8_t channel);
+
+    /** Stop the interface
+     *  @return             0 on success, negative on failure
+     */
+    virtual nsapi_error_t disconnect();
+
+    /** Get the internally stored IP address
+     *  @return             IP address of the interface or null if not yet connected
+     */
+    virtual const char *get_ip_address();
+
+    /** Get the internally stored MAC address
+     *  @return             MAC address of the interface
+     */
+    virtual const char *get_mac_address();
+
+    /** Get the local gateway
+     *
+     *  @return         Null-terminated representation of the local gateway
+     *                  or null if no network mask has been recieved
+     */
+    virtual const char *get_gateway();
+
+    /** Get the local network mask
+     *
+     *  @return         Null-terminated representation of the local network mask
+     *                  or null if no network mask has been recieved
+     */
+    virtual const char *get_netmask();
+
+    /** Gets the current radio signal strength for active connection
+     *
+     * @return          Connection strength in dBm (negative value)
+     */
+    virtual int8_t get_rssi();
+
+    /** Scan for available networks
+     *
+     *  This function will block. If the @a count is 0, function will only return count of available networks, so that
+     *  user can allocated necessary memory. If the @count is grater than 0 and the @a ap is not NULL it'll be populated
+     *  with discovered networks up to value of @a count.
+     *
+     *  @param  res      Pointer to allocated array to store discovered AP
+     *  @param  count    Size of allocated @a res array, or 0 to only count available AP
+     *  @return          Number of entries in @a, or if @a count was 0 number of available networks,
+     *                   negative on error see @a nsapi_error
+     */
+    virtual nsapi_size_or_error_t scan(WiFiAccessPoint *res, unsigned count);
+
+    /** Translates a hostname to an IP address with specific version
+     *
+     *  The hostname may be either a domain name or an IP address. If the
+     *  hostname is an IP address, no network transactions will be performed.
+     *
+     *  If no stack-specific DNS resolution is provided, the hostname
+     *  will be resolve using a UDP socket on the stack.
+     *
+     *  @param address  Destination for the host SocketAddress
+     *  @param host     Hostname to resolve
+     *  @param version  IP version of address to resolve, NSAPI_UNSPEC indicates
+     *                  version is chosen by the stack (defaults to NSAPI_UNSPEC)
+     *  @return         0 on success, negative error code on failure
+     */
+    using NetworkInterface::gethostbyname;
+
+    /** Add a domain name server to list of servers to query
+     *
+     *  @param addr     Destination for the host address
+     *  @return         0 on success, negative error code on failure
+     */
+    using NetworkInterface::add_dns_server;
+
+private:
+    /** Open a socket
+     *  @param handle       Handle in which to store new socket
+     *  @param proto        Type of socket to open, NSAPI_TCP or NSAPI_UDP
+     *  @return             0 on success, negative on failure
+     */
+    virtual nsapi_error_t socket_open(void **handle, nsapi_protocol_t proto);
+
+    /** Close the socket
+     *  @param handle       Socket handle
+     *  @return             0 on success, negative on failure
+     *  @note On failure, any memory associated with the socket must still
+     *        be cleaned up
+     */
+    virtual nsapi_error_t socket_close(void *handle);
+
+    /** Bind a server socket to a specific port - NOT SUPPORTED
+     *
+     *  This function is not supported and will return NSAPI_ERROR_UNSUPPORTED
+     *
+     *  @param handle       Socket handle
+     *  @param address      Local address to listen for incoming connections on
+     *  @return             Not supported, returns NSAPI_ERROR_UNSUPPORTED
+     */
+    virtual nsapi_error_t socket_bind(void *handle, const SocketAddress &address);
+
+    /** Start listening for incoming connectionst - NOT SUPPORTED
+     *
+     *  This function is not supported and will return NSAPI_ERROR_UNSUPPORTED
+     *
+     *  @param handle       Socket handle
+     *  @param backlog      Number of pending connections that can be queued up at any
+     *                      one time [Default: 1]
+     *  @return             Not supported, returns NSAPI_ERROR_UNSUPPORTED
+     */
+    virtual nsapi_error_t socket_listen(void *handle, int backlog);
+
+    /** Connects this TCP socket to the server
+     *  @param handle       Socket handle
+     *  @param address      SocketAddress to connect to
+     *  @return             0 on success, negative on failure
+     */
+    virtual nsapi_error_t socket_connect(void *handle, const SocketAddress &address);
+
+    /** Accept a new connection - NOT SUPPORTED
+     *
+     *  This function is not supported and will return NSAPI_ERROR_UNSUPPORTED
+     *
+     *  @param handle       Handle in which to store new socket
+     *  @param server       Socket handle to server to accept from
+     *  @return             Not supported, returns NSAPI_ERROR_UNSUPPORTED
+     */
+    virtual nsapi_error_t socket_accept(void *handle, void **socket, SocketAddress *address);
+
+    /** Send data to the remote host
+     *  @param handle       Socket handle
+     *  @param data         The buffer to send to the host
+     *  @param size         The length of the buffer to send
+     *  @return             Number of written bytes on success, negative on failure
+     *  @note This call is not-blocking, if this call would block, must
+     *        immediately return NSAPI_ERROR_WOULD_WAIT
+     */
+    virtual nsapi_size_or_error_t socket_send(void *handle, const void *data, unsigned size);
+
+    /** Receive data from the remote host
+     *  @param handle       Socket handle
+     *  @param data         The buffer in which to store the data received from the host
+     *  @param size         The maximum length of the buffer
+     *  @return             Number of received bytes on success, negative on failure
+     *  @note This call is not-blocking, if this call would block, must
+     *        immediately return NSAPI_ERROR_WOULD_WAIT
+     */
+    virtual nsapi_size_or_error_t socket_recv(void *handle, void *data, unsigned size);
+
+    /** Send a packet to a remote endpoint
+     *  @param handle       Socket handle
+     *  @param address      The remote SocketAddress
+     *  @param data         The packet to be sent
+     *  @param size         The length of the packet to be sent
+     *  @return             The number of written bytes on success, negative on failure
+     *  @note This call is not-blocking, if this call would block, must
+     *        immediately return NSAPI_ERROR_WOULD_WAIT
+     */
+    virtual nsapi_size_or_error_t socket_sendto(void *handle, const SocketAddress &address, const void *data, unsigned size);
+
+    /** Receive a packet from a remote endpoint
+     *  @param handle       Socket handle
+     *  @param address      Destination for the remote SocketAddress or null
+     *  @param buffer       The buffer for storing the incoming packet data
+     *                      If a packet is too long to fit in the supplied buffer,
+     *                      excess bytes are discarded
+     *  @param size         The length of the buffer
+     *  @return             The number of received bytes on success, negative on failure
+     *  @note This call is not-blocking, if this call would block, must
+     *        immediately return NSAPI_ERROR_WOULD_WAIT
+     */
+    virtual nsapi_size_or_error_t socket_recvfrom(void *handle, SocketAddress *address, void *buffer, unsigned size);
+
+    /** Register a callback on state change of the socket
+     *  @param handle       Socket handle
+     *  @param callback     Function to call on state change
+     *  @param data         Argument to pass to callback
+     *  @note Callback may be called in an interrupt context.
+     */
+    virtual void socket_attach(void *handle, void (*callback)(void *), void *data);
+
+    /** Provide access to the NetworkStack object
+     *
+     *  @return The underlying NetworkStack object
+     */
+    virtual NetworkStack *get_stack()
+    {
+        return this;
+    }
+
+private:
+    /** spwf_socket class
+     *  Implementation of SPWF socket structure
+     */
+    typedef struct spwf_socket {
+        int8_t internal_id;
+        int spwf_id;
+        bool server_gone;
+        bool no_more_data;
+        nsapi_protocol_t proto;
+        SocketAddress addr;
+    } spwf_socket_t;
+
+    bool _socket_is_open(spwf_socket_t *sock) {
+        if(sock->internal_id != SPWFSA_SOCKET_COUNT) {
+            return (_ids[sock->internal_id].internal_id == sock->internal_id);
+        }
+        return false;
+    }
+
+    bool _socket_has_connected(spwf_socket_t *sock) {
+        return (_socket_is_open(sock) && (sock->spwf_id != SPWFSA_SOCKET_COUNT));
+    }
+
+    bool _socket_is_still_connected(spwf_socket_t *sock) {
+        return (_socket_has_connected(sock) && !sock->server_gone);
+    }
+
+    bool _socket_might_have_data(spwf_socket_t *sock) {
+        return (_socket_has_connected(sock) && !sock->no_more_data);
+    }
+
+    bool _socket_is_open(int internal_id) {
+        if(internal_id != SPWFSA_SOCKET_COUNT) {
+            return (_ids[internal_id].internal_id == internal_id);
+        }
+        return false;
+    }
+
+    bool _socket_has_connected(int internal_id) {
+        if(!_socket_is_open(internal_id)) return false;
+
+        spwf_socket_t &sock = _ids[internal_id];
+        return (sock.spwf_id != SPWFSA_SOCKET_COUNT);
+    }
+
+    bool _socket_is_still_connected(int internal_id) {
+        if(!_socket_has_connected(internal_id)) return false;
+
+        spwf_socket_t &sock = _ids[internal_id];
+        return (!sock.server_gone);
+    }
+
+    bool _socket_might_have_data(int internal_id) {
+        if(!_socket_is_still_connected(internal_id)) return false;
+
+        spwf_socket_t &sock = _ids[internal_id];
+        return (!sock.no_more_data);
+    }
+
+#if MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW01M1
+    SPWFSA01 _spwf;
+#elif MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1
+    SPWFSA04 _spwf;
+#endif
+
+    bool _isInitialized;
+    bool _dbg_on;
+    bool _connected_to_network;
+
+    spwf_socket_t _ids[SPWFSA_SOCKET_COUNT];
+    struct {
+        void (*callback)(void *);
+        void *data;
+    } _cbs[SPWFSA_SOCKET_COUNT];
+    int _internal_ids[SPWFSA_SOCKET_COUNT];
+
+    char ap_ssid[33]; /* 32 is what 802.11 defines as longest possible name; +1 for the \0 */
+    nsapi_security_t ap_sec;
+    char ap_pass[64]; /* The longest allowed passphrase */
+
+private:
+    void event(void);
+    nsapi_error_t init(void);
+
+    int get_internal_id(int spwf_id) { // checks also if `spwf_id` is still "valid"
+        MBED_ASSERT(spwf_id != SPWFSA_SOCKET_COUNT);
+
+        int internal_id = _internal_ids[spwf_id];
+        if((_socket_is_open(internal_id)) && (_ids[internal_id].spwf_id == spwf_id)) {
+            return internal_id;
+        } else {
+            return SPWFSA_SOCKET_COUNT;
+        }
+    }
+
+    /* Called at initialization or after module hard fault */
+    void inner_constructor() {
+        memset(_ids, 0, sizeof(_ids));
+        memset(_cbs, 0, sizeof(_cbs));
+
+        for (int sock_cnt = 0; sock_cnt < SPWFSA_SOCKET_COUNT; sock_cnt++) {
+            _ids[sock_cnt].internal_id = SPWFSA_SOCKET_COUNT;
+            _ids[sock_cnt].spwf_id = SPWFSA_SOCKET_COUNT;
+            _internal_ids[sock_cnt] = SPWFSA_SOCKET_COUNT;
+        }
+
+        _spwf.attach(this, &SpwfSAInterface::event);
+
+        _connected_to_network = false;
+        _isInitialized = false;
+    }
+
+private:
+    friend class SPWFSAxx;
+    friend class SPWFSA01;
+    friend class SPWFSA04;
+};
+
+#define CHECK_NOT_CONNECTED_ERR() { \
+        if(!_connected_to_network) return NSAPI_ERROR_NO_CONNECTION; \
+} \
+
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-x-nucleo-idw01m1/mbed_app_idw01m1.json	Wed Oct 28 07:42:46 2020 +0000
@@ -0,0 +1,9 @@
+{
+    "target_overrides": {
+        "*": {
+            "idw0xx1.expansion-board": "IDW01M1",
+	    "drivers.uart-serial-txbuf-size": 730,
+	    "drivers.uart-serial-rxbuf-size": 730
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-x-nucleo-idw01m1/mbed_app_idw04a1.json	Wed Oct 28 07:42:46 2020 +0000
@@ -0,0 +1,10 @@
+{
+    "target_overrides": {
+        "*": {
+            "idw0xx1.expansion-board": "IDW04A1",
+	    "drivers.uart-serial-txbuf-size": 750,
+	    "drivers.uart-serial-rxbuf-size": 750
+        }
+    },
+    "macros": ["IDW04A1_WIFI_HW_BUG_WA"]
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-x-nucleo-idw01m1/mbed_lib.json	Wed Oct 28 07:42:46 2020 +0000
@@ -0,0 +1,9 @@
+{
+    "name": "idw0xx1",
+    "config": {
+        "expansion-board":{
+	    "help": "Options are IDW01M1 and IDW04A1",
+	    "value": "IDW01M1"
+        }
+    }
+}