Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Revision 0:5738799d7a56, committed 2020-10-28
- Comitter:
- axelhwang
- Date:
- Wed Oct 28 07:42:46 2020 +0000
- Commit message:
- Push
Changed in this revision
--- /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>© 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>© 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"
+ }
+ }
+}