diff --git a/Documentation/platforms/xtensa/esp32s2/index.rst b/Documentation/platforms/xtensa/esp32s2/index.rst index 93aa992b4a4..e88bbc0e094 100644 --- a/Documentation/platforms/xtensa/esp32s2/index.rst +++ b/Documentation/platforms/xtensa/esp32s2/index.rst @@ -217,7 +217,7 @@ Timers Yes Touch Yes UART Yes Watchdog Yes -Wifi No +Wifi Yes ========== ======= ===== Memory Map @@ -364,6 +364,50 @@ audio subsystem and develop specific usages of the I2S peripheral. Please check for usage examples using the :doc:`ESP32-S2-Saola-1 `. +Wi-Fi +====== + +.. tip:: Boards usually expose a ``wifi`` defconfig which enables Wi-Fi. + +A standard network interface will be configured and can be initialized such as:: + + nsh> ifup wlan0 + nsh> wapi psk wlan0 mypasswd 3 + nsh> wapi essid wlan0 myssid 1 + nsh> renew wlan0 + +In this case a connection to AP with SSID ``myssid`` is done, using ``mypasswd`` as +password. IP address is obtained via DHCP using ``renew`` command. You can check +the result by running ``ifconfig`` afterwards. + +.. tip:: Please refer to :ref:`ESP32 Wi-Fi Station Mode ` + for more information. + +Wi-Fi SoftAP +============ + +It is possible to use ESP32-S2 as an Access Point (SoftAP). + +.. tip:: Boards usually expose a ``sta_softap`` defconfig which enables Wi-Fi + (STA + SoftAP). + +If you are using this board config profile you can run these commands to be able +to connect your smartphone or laptop to your board:: + + nsh> ifup wlan1 + nsh> dhcpd_start wlan1 + nsh> wapi psk wlan1 mypasswd 3 + nsh> wapi essid wlan1 nuttxap 1 + +In this case, you are creating the access point ``nuttxapp`` in your board and to +connect to it on your smartphone you will be required to type the password ``mypasswd`` +using WPA2. + +.. tip:: Please refer to :ref:`ESP32 Wi-Fi SoftAP Mode ` + for more information. + +The ``dhcpd_start`` is necessary to let your board to associate an IP to your smartphone. + Secure Boot and Flash Encryption ================================ diff --git a/arch/xtensa/include/esp32s2/irq.h b/arch/xtensa/include/esp32s2/irq.h index 9c7e4734d9e..d1bc8b12561 100644 --- a/arch/xtensa/include/esp32s2/irq.h +++ b/arch/xtensa/include/esp32s2/irq.h @@ -59,8 +59,12 @@ * sources. */ -/* RESERVED interrupts: 0, 1, 3, 4, 5, 6, 7, 8, 9 */ +/* RESERVED interrupts: 0, 1, 3, 4, 5, 6, 7, 8, 9 + * 0 and 1 are the exception because it is required for WiFi. + */ +#define ESP32S2_PERIPH_MAC 0 +#define ESP32S2_PERIPH_MAC_NMI 1 #define ESP32S2_PERIPH_PWR 2 /* RESERVED interrupts: 10, 11, 12, 14 */ @@ -197,6 +201,9 @@ #define ESP32S2_IRQ2PERIPH(irq) ((irq) - XTENSA_IRQ_FIRSTPERIPH) #define ESP32S2_PERIPH2IRQ(id) ((id) + XTENSA_IRQ_FIRSTPERIPH) +#define ESP32S2_IRQ_MAC (XTENSA_IRQ_FIRSTPERIPH + ESP32S2_PERIPH_MAC) +#define ESP32S2_IRQ_MAC_NMI (XTENSA_IRQ_FIRSTPERIPH + ESP32S2_PERIPH_MAC_NMI) + #define ESP32S2_IRQ_PWR (XTENSA_IRQ_FIRSTPERIPH + ESP32S2_PERIPH_PWR) #define ESP32S2_IRQ_UHCI0 (XTENSA_IRQ_FIRSTPERIPH + ESP32S2_PERIPH_UHCI0) @@ -415,6 +422,7 @@ #define ESP32S2_CPUINT_NMISET 0x00004000 #define ESP32S2_CPUINT_MAC 0 +#define ESP32S2_CPUINT_PWR 0 #define ESP32S2_CPUINT_TIMER0 6 #define ESP32S2_CPUINT_SOFTWARE0 7 #define ESP32S2_CPUINT_PROFILING 11 diff --git a/arch/xtensa/src/common/espressif/Kconfig b/arch/xtensa/src/common/espressif/Kconfig index a8cc38bad28..361f4c221e5 100644 --- a/arch/xtensa/src/common/espressif/Kconfig +++ b/arch/xtensa/src/common/espressif/Kconfig @@ -153,3 +153,191 @@ config ESPRESSIF_STORAGE_MTD_DEBUG endif # ESPRESSIF_SPIFLASH endmenu # SPI Flash Configuration + +config ESPRESSIF_WIRELESS + bool + default n + select NET + select ARCH_PHY_INTERRUPT + select ESP32S2_RNG if ARCH_CHIP_ESP32S2 + select ESP32S2_RT_TIMER if ARCH_CHIP_ESP32S2 + select ESP32S2_TIMER0 if ARCH_CHIP_ESP32S2 + depends on ARCH_CHIP_ESP32S2 + ---help--- + Enable Wireless support + +config ESPRESSIF_WIFI + bool "Wi-Fi" + default n + select ESPRESSIF_WIRELESS + ---help--- + Enable Wi-Fi support + +menu "Wi-Fi Configuration" + depends on ESPRESSIF_WIFI + +menu "ESP WPA-Supplicant" + +config WPA_WAPI_PSK + bool "Enable WAPI PSK support" + default n + ---help--- + Select this option to enable WAPI-PSK + which is a Chinese National Standard Encryption for Wireless LANs (GB 15629.11-2003). + +config WPA_SUITE_B_192 + bool "Enable NSA suite B support with 192-bit key" + default n + select ESP_WIFI_GCMP_SUPPORT + select ESP_WIFI_GMAC_SUPPORT + ---help--- + Select this option to enable 192-bit NSA suite-B. + This is necessary to support WPA3 192-bit security. + +config ESP_WPA_DEBUG_PRINT + bool "Print debug messages from Espressif's WPA Supplicant" + default n + ---help--- + Select this option to print logging information from WPA supplicant, + this includes handshake information and key hex dumps depending + on the project logging level. + + Enabling this could increase the build size ~60kb + depending on the project logging level. + +endmenu # ESP WPA-Supplicant + +choice ESPRESSIF_WIFI_MODE + prompt "ESP Wi-Fi mode" + default ESPRESSIF_WIFI_STATION + +config ESPRESSIF_WIFI_STATION + bool "Station mode" + +config ESPRESSIF_WIFI_SOFTAP + bool "SoftAP mode" + +config ESPRESSIF_WIFI_STATION_SOFTAP + bool "Station + SoftAP" + +endchoice # ESP Wi-Fi mode + +config ESP_WIFI_ENABLE_SAE_PK + bool "Enable SAE-PK" + default y + ---help--- + Select this option to enable SAE-PK + +config ESP_WIFI_ENABLE_WPA3_OWE_STA + bool "Enable OWE STA" + default y + ---help--- + Select this option to allow the device to establish OWE connection with eligible AP's. + PMF (Protected Management Frames) is a prerequisite feature for a WPA3 connection, it needs to be + explicitly configured before attempting connection. Please refer to the Wi-Fi Driver API Guide for details. + +config ESPRESSIF_WIFI_STATIC_RXBUF_NUM + int "Wi-Fi static RX buffer number" + default 10 + +config ESPRESSIF_WIFI_DYNAMIC_RXBUF_NUM + int "Wi-Fi dynamic RX buffer number" + default 32 + +config ESPRESSIF_WIFI_DYNAMIC_TXBUF_NUM + int "Wi-Fi dynamic TX buffer number" + default 32 + +config ESPRESSIF_WIFI_TX_AMPDU + bool "Wi-Fi TX AMPDU" + default y + +config ESPRESSIF_WIFI_RX_AMPDU + bool "Wi-Fi RX AMPDU" + default y + +config ESPRESSIF_WIFI_RXBA_AMPDU_WZ + int "Wi-Fi RX BA AMPDU windown size" + default 6 + +config ESPRESSIF_WLAN_PKTBUF_NUM + int "WLAN netcard packet buffer number per netcard" + default 16 + +config ESP_WIFI_GCMP_SUPPORT + bool "WiFi GCMP Support(GCMP128 and GCMP256)" + default n + ---help--- + Select this option to enable GCMP support. GCMP support is compulsory for WiFi Suite-B support. + +config ESP_WIFI_GMAC_SUPPORT + bool "WiFi GMAC Support(GMAC128 and GMAC256)" + default n + ---help--- + Select this option to enable GMAC support. GMAC support is compulsory for WiFi 192-bit certification. + +config ESPRESSIF_WIFI_CONNECT_TIMEOUT + int "Connect timeout in second" + default 10 + ---help--- + Max waiting time of connecting to AP. + +config ESPRESSIF_WIFI_SCAN_RESULT_SIZE + int "Scan result buffer" + default 4096 + ---help--- + Maximum scan result buffer size. + +config ESPRESSIF_WIFI_STA_DISCONNECT_PM + bool "Power Management for station when disconnected" + default y + ---help--- + Select this option to enable power management for station when disconnected. + Chip will do modem-sleep when RF module is not in use anymore. + +choice ESPRESSIF_POWER_SAVE_MODE + prompt "Wi-Fi Power save mode" + default ESPRESSIF_POWER_SAVE_NONE + ---help--- + Wi-Fi supports the Modem-sleep mode which refers to the legacy power-saving mode in the IEEE 802.11 protocol. + Modem-sleep mode works in station-only mode and the station must connect to the AP first. If the Modem-sleep + mode is enabled, station will switch between active and sleep state periodically. In sleep state, RF, PHY and + BB are turned off in order to reduce power consumption. Station can keep connection with AP in modem-sleep mode. + + Modem-sleep mode includes minimum and maximum power-saving modes. + + In minimum power-saving mode, station wakes + up every DTIM to receive beacon. Broadcast data will not be lost because it is transmitted after DTIM. + However, it cannot save much more power if DTIM is short for DTIM is determined by AP. + + In maximum power-saving mode, station wakes up in every listen interval to receive beacon. This listen interval + can be set to be longer than the AP DTIM period. Broadcast data may be lost because station may be in sleep + state at DTIM time. If listen interval is longer, more power is saved, but broadcast data is more easy to lose. + Listen interval can be configured by setting ESPRESSIF_WIFI_LISTEN_INTERVAL. + + ESPRESSIF_POWER_SAVE_NONE disables Modem-sleep mode entirely. Disabling it increases power consumption, but + minimizes the delay in receiving Wi-Fi data in real time. When Modem-sleep mode is enabled, the delay in + receiving Wi-Fi data may be the same as the DTIM cycle (minimum power-saving mode) or the listening interval + (maximum power-saving mode). Setting ESPRESSIF_POWER_SAVE_NONE is suitable when high throughput is required. + +config ESPRESSIF_POWER_SAVE_NONE + bool "No power save" + +config ESPRESSIF_POWER_SAVE_MIN_MODEM + bool "Minimum modem power saving." + +config ESPRESSIF_POWER_SAVE_MAX_MODEM + bool "Maximum modem power saving" + +endchoice # ESPRESSIF_POWER_SAVE_MODE + +config ESPRESSIF_WIFI_LISTEN_INTERVAL + int "Wi-Fi listen interval" + depends on ESPRESSIF_POWER_SAVE_MAX_MODEM + default 3 + ---help--- + Interval for station to listen to beacon from AP. The unit of listen interval is one beacon interval. + For example, if beacon interval is 100 ms and listen interval is 3, the interval for station to listen + to beacon is 300 ms. + +endmenu # ESPRESSIF_WIFI diff --git a/arch/xtensa/src/common/espressif/Make.defs b/arch/xtensa/src/common/espressif/Make.defs index 31182e18a20..58b2a6f4b0c 100644 --- a/arch/xtensa/src/common/espressif/Make.defs +++ b/arch/xtensa/src/common/espressif/Make.defs @@ -47,4 +47,16 @@ CHIP_CSRCS += esp_spiflash_mtd.c endif endif +ifeq ($(CONFIG_ESPRESSIF_WIRELESS),y) +CHIP_CSRCS += esp_wireless.c +ifeq ($(CONFIG_ESPRESSIF_WIFI),y) +CHIP_CSRCS += esp_wifi_utils.c +CHIP_CSRCS += esp_wlan.c +endif +endif + +ifeq ($(CONFIG_ESPRESSIF_WIRELESS),y) +include common$(DELIM)espressif$(DELIM)Wireless.mk +endif + INCLUDES += ${INCDIR_PREFIX}$(ARCH_SRCDIR)$(DELIM)common$(DELIM)espressif$(DELIM)platform_include diff --git a/arch/xtensa/src/common/espressif/Wireless.mk b/arch/xtensa/src/common/espressif/Wireless.mk new file mode 100644 index 00000000000..016206410d6 --- /dev/null +++ b/arch/xtensa/src/common/espressif/Wireless.mk @@ -0,0 +1,242 @@ +############################################################################ +# arch/xtensa/src/common/espressif/Wireless.mk +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you 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. +# +############################################################################ + +INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)soc$(DELIM)$(CHIP_SERIES)$(DELIM)include +INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)nuttx$(DELIM)$(CHIP_SERIES)$(DELIM)include +INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)nuttx$(DELIM)include$(DELIM)esp_wifi + +EXTRA_LIBPATHS += -L $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_phy$(DELIM)lib$(DELIM)$(CHIP_SERIES) +EXTRA_LIBPATHS += -L $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_wifi$(DELIM)lib$(DELIM)$(CHIP_SERIES) + +EXTRA_LIBS += -lphy + +ifeq ($(CONFIG_ESPRESSIF_WIFI),y) +EXTRA_LIBS += -lcore -lnet80211 -lpp + +ifeq ($(CONFIG_WPA_WAPI_PSK),y) +EXTRA_LIBS += -lwapi +endif + +## ESP-IDF's mbedTLS + +VPATH += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)mbedtls$(DELIM)mbedtls$(DELIM)library + +INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)mbedtls$(DELIM)mbedtls$(DELIM)include +INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)mbedtls$(DELIM)mbedtls$(DELIM)library +INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)mbedtls$(DELIM)port$(DELIM)include +INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)nuttx$(DELIM)include$(DELIM)mbedtls + +### Define Espressif's configs for mbedTLS + +CFLAGS += $(DEFINE_PREFIX)MBEDTLS_CONFIG_FILE="" + +CHIP_CSRCS += aes.c +CHIP_CSRCS += aria.c +CHIP_CSRCS += bignum_core.c +CHIP_CSRCS += bignum.c +CHIP_CSRCS += ccm.c +CHIP_CSRCS += cipher_wrap.c +CHIP_CSRCS += cipher.c +CHIP_CSRCS += cmac.c +CHIP_CSRCS += constant_time.c +CHIP_CSRCS += ctr_drbg.c +CHIP_CSRCS += ecp_curves.c +CHIP_CSRCS += ecp.c +CHIP_CSRCS += entropy.c +CHIP_CSRCS += gcm.c +CHIP_CSRCS += md.c +CHIP_CSRCS += pkcs5.c +CHIP_CSRCS += platform_util.c +CHIP_CSRCS += platform.c +CHIP_CSRCS += sha1.c +CHIP_CSRCS += sha3.c +CHIP_CSRCS += sha256.c +CHIP_CSRCS += sha512.c +CHIP_CSRCS += pk.c +CHIP_CSRCS += pk_wrap.c +CHIP_CSRCS += pkparse.c +CHIP_CSRCS += ecdsa.c +CHIP_CSRCS += asn1parse.c +CHIP_CSRCS += asn1write.c +CHIP_CSRCS += rsa.c +CHIP_CSRCS += md5.c +CHIP_CSRCS += oid.c +CHIP_CSRCS += pem.c +CHIP_CSRCS += hmac_drbg.c +CHIP_CSRCS += rsa_alt_helpers.c +CHIP_CSRCS += ecdh.c +CHIP_CSRCS += pk_ecc.c + +VPATH += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)mbedtls$(DELIM)port + +CHIP_CSRCS += esp_hardware.c +CHIP_CSRCS += esp_mem.c +CHIP_CSRCS += esp_timing.c + +VPATH += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)mbedtls$(DELIM)port$(DELIM)md + +CHIP_CSRCS += esp_md.c + +## WPA Supplicant + +WIFI_WPA_SUPPLICANT = chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)wpa_supplicant + +CFLAGS += $(DEFINE_PREFIX)__ets__ +CFLAGS += $(DEFINE_PREFIX)CONFIG_CRYPTO_MBEDTLS +CFLAGS += $(DEFINE_PREFIX)CONFIG_ECC +CFLAGS += $(DEFINE_PREFIX)CONFIG_IEEE80211W +CFLAGS += $(DEFINE_PREFIX)CONFIG_WPA3_SAE +CFLAGS += $(DEFINE_PREFIX)EAP_PEER_METHOD +CFLAGS += $(DEFINE_PREFIX)ESP_PLATFORM=1 +CFLAGS += $(DEFINE_PREFIX)ESP_SUPPLICANT +CFLAGS += $(DEFINE_PREFIX)ESPRESSIF_USE +CFLAGS += $(DEFINE_PREFIX)IEEE8021X_EAPOL +CFLAGS += $(DEFINE_PREFIX)USE_WPA2_TASK +CFLAGS += $(DEFINE_PREFIX)CONFIG_SHA256 +CFLAGS += $(DEFINE_PREFIX)CONFIG_SAE +CFLAGS += $(DEFINE_PREFIX)USE_WPS_TASK + +ifeq ($(CONFIG_ESP_WIFI_ENABLE_SAE_PK),y) +CFLAGS += $(DEFINE_PREFIX)CONFIG_SAE_PK +endif + +ifeq ($(CONFIG_ESP_WIFI_ENABLE_WPA3_OWE_STA),y) +CFLAGS += $(DEFINE_PREFIX)CONFIG_OWE_STA +endif + +ifeq ($(CONFIG_ESP_WIFI_GCMP_SUPPORT),y) +CFLAGS += $(DEFINE_PREFIX)CONFIG_GCMP +endif + +ifeq ($(CONFIG_ESP_WIFI_GMAC_SUPPORT),y) +CFLAGS += $(DEFINE_PREFIX)CONFIG_GMAC +endif + +INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)$(WIFI_WPA_SUPPLICANT)$(DELIM)include +INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)$(WIFI_WPA_SUPPLICANT)$(DELIM)src + +VPATH += $(WIFI_WPA_SUPPLICANT)$(DELIM)src$(DELIM)ap + +INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)$(WIFI_WPA_SUPPLICANT)$(DELIM)src$(DELIM)ap + +CHIP_CSRCS += ap_config.c +CHIP_CSRCS += ieee802_11.c +CHIP_CSRCS += comeback_token.c +CHIP_CSRCS += pmksa_cache_auth.c +CHIP_CSRCS += sta_info.c +CHIP_CSRCS += wpa_auth_ie.c +CHIP_CSRCS += wpa_auth.c + +VPATH += $(WIFI_WPA_SUPPLICANT)$(DELIM)src$(DELIM)common + +INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)$(WIFI_WPA_SUPPLICANT)$(DELIM)src$(DELIM)common + +CHIP_CSRCS += dragonfly.c +CHIP_CSRCS += sae.c +CHIP_CSRCS += wpa_common.c +CHIP_CSRCS += sae_pk.c +CHIP_CSRCS += bss.c +CHIP_CSRCS += scan.c +CHIP_CSRCS += ieee802_11_common.c + +VPATH += $(WIFI_WPA_SUPPLICANT)$(DELIM)src$(DELIM)crypto + +CHIP_CSRCS += aes-ccm.c +CHIP_CSRCS += aes-gcm.c +CHIP_CSRCS += aes-omac1.c +CHIP_CSRCS += aes-unwrap.c +CHIP_CSRCS += aes-wrap.c +CHIP_CSRCS += ccmp.c +CHIP_CSRCS += crypto_ops.c +CHIP_CSRCS += des-internal.c +CHIP_CSRCS += dh_groups.c +CHIP_CSRCS += rc4.c +CHIP_CSRCS += sha1-prf.c +CHIP_CSRCS += sha256-kdf.c +CHIP_CSRCS += sha256-prf.c + +VPATH += $(WIFI_WPA_SUPPLICANT)$(DELIM)src$(DELIM)eap_peer + +CHIP_CSRCS += chap.c +CHIP_CSRCS += eap_common.c +CHIP_CSRCS += eap_mschapv2.c +CHIP_CSRCS += eap_peap_common.c +CHIP_CSRCS += eap_peap.c +CHIP_CSRCS += eap_tls_common.c +CHIP_CSRCS += eap_tls.c +CHIP_CSRCS += eap_ttls.c +CHIP_CSRCS += eap.c +CHIP_CSRCS += mschapv2.c + +VPATH += $(WIFI_WPA_SUPPLICANT)$(DELIM)src$(DELIM)rsn_supp + +CHIP_CSRCS += pmksa_cache.c +CHIP_CSRCS += wpa_ie.c +CHIP_CSRCS += wpa.c + +VPATH += $(WIFI_WPA_SUPPLICANT)$(DELIM)src$(DELIM)utils + +INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)$(WIFI_WPA_SUPPLICANT)$(DELIM)src$(DELIM)utils + +CHIP_CSRCS += base64.c +CHIP_CSRCS += bitfield.c +CHIP_CSRCS += common.c +CHIP_CSRCS += ext_password.c +CHIP_CSRCS += json.c +CHIP_CSRCS += uuid.c +CHIP_CSRCS += wpa_debug.c +CHIP_CSRCS += wpabuf.c + +VPATH += $(WIFI_WPA_SUPPLICANT)$(DELIM)port + +INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)$(WIFI_WPA_SUPPLICANT)$(DELIM)port$(DELIM)include + +CHIP_CSRCS += eloop.c +CHIP_CSRCS += os_xtensa.c + +## ESP Supplicant (Espressif's WPA supplicant extension) + +INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)$(WIFI_WPA_SUPPLICANT)$(DELIM)esp_supplicant$(DELIM)include + +VPATH += $(WIFI_WPA_SUPPLICANT)$(DELIM)esp_supplicant$(DELIM)src + +INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)$(WIFI_WPA_SUPPLICANT)$(DELIM)esp_supplicant$(DELIM)src + +CHIP_CSRCS += esp_common.c +CHIP_CSRCS += esp_hostap.c +CHIP_CSRCS += esp_wpa_main.c +CHIP_CSRCS += esp_wpa3.c +CHIP_CSRCS += esp_wpas_glue.c +CHIP_CSRCS += esp_owe.c +CHIP_CSRCS += esp_scan.c +CHIP_CSRCS += esp_wps.c + +VPATH += $(WIFI_WPA_SUPPLICANT)$(DELIM)esp_supplicant$(DELIM)src$(DELIM)crypto + +INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)$(WIFI_WPA_SUPPLICANT)$(DELIM)src$(DELIM)crypto + +CHIP_CSRCS += crypto_mbedtls-bignum.c +CHIP_CSRCS += crypto_mbedtls-ec.c +CHIP_CSRCS += crypto_mbedtls-rsa.c +CHIP_CSRCS += crypto_mbedtls.c +CHIP_CSRCS += tls_mbedtls.c +CHIP_CSRCS += aes-siv.c + +endif diff --git a/arch/xtensa/src/common/espressif/esp_wifi_utils.c b/arch/xtensa/src/common/espressif/esp_wifi_utils.c new file mode 100644 index 00000000000..2247715554e --- /dev/null +++ b/arch/xtensa/src/common/espressif/esp_wifi_utils.c @@ -0,0 +1,577 @@ +/**************************************************************************** + * arch/xtensa/src/common/espressif/esp_wifi_utils.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include + +#ifdef CONFIG_ARCH_CHIP_ESP32S2 +#include "esp32s2_wifi_adapter.h" +#endif + +#include "esp_wifi_utils.h" +#include "esp_wireless.h" + +#include "esp_log.h" +#include "esp_mac.h" +#include "esp_private/phy.h" +#include "esp_private/wifi.h" +#include "esp_random.h" +#include "esp_timer.h" +#include "esp_wpa.h" +#include "rom/ets_sys.h" +#include "soc/soc_caps.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Helper to get iw_event size */ + +#define ESP_IW_EVENT_SIZE(field) \ + (offsetof(struct iw_event, u) + sizeof(((union iwreq_data *)0)->field)) + +#ifdef CONFIG_ESPRESSIF_WIFI_SCAN_RESULT_SIZE +# define WIFI_SCAN_RESULT_SIZE CONFIG_ESPRESSIF_WIFI_SCAN_RESULT_SIZE +#else +# define WIFI_SCAN_RESULT_SIZE (4096) +#endif + +#define SCAN_TIME_SEC (5) + +/* Maximum number of channels for Wi-Fi 2.4Ghz */ + +#define CHANNEL_MAX_NUM (14) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +enum scan_status_e +{ + ESP_SCAN_DISABLED = 0, + ESP_SCAN_RUN, + ESP_SCAN_DONE +}; + +/* Wi-Fi scan result information */ + +struct wifi_scan_result +{ + enum scan_status_e scan_status; /* Scan status */ + sem_t scan_signal; /* Scan notification signal */ + uint8_t *scan_result; /* Temp buffer that holds results */ + unsigned int scan_result_size; /* Current size of temp buffer */ +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct wifi_scan_result g_scan_priv = +{ + .scan_signal = SEM_INITIALIZER(0), +}; +static uint8_t g_channel_num; +static uint8_t g_channel_list[CHANNEL_MAX_NUM]; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: esp_wifi_start_scan + * + * Description: + * Scan all available APs. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_start_scan(struct iwreq *iwr) +{ + struct wifi_scan_result *priv = &g_scan_priv; + wifi_scan_config_t *config = NULL; + struct iw_scan_req *req; + int ret = 0; + int i; + uint8_t target_mac[MAC_LEN]; + uint8_t target_ssid[SSID_MAX_LEN + 1]; + memset(target_ssid, 0x0, sizeof(SSID_MAX_LEN + 1)); + + if (iwr == NULL) + { + wlerr("ERROR: Invalid ioctl cmd.\n"); + return -EINVAL; + } + + if (g_scan_priv.scan_status != ESP_SCAN_DISABLED) + { + return OK; + } + + config = kmm_calloc(1, sizeof(wifi_scan_config_t)); + if (config == NULL) + { + wlerr("ERROR: Cannot allocate result buffer\n"); + return -ENOMEM; + } + + g_channel_num = 0; + memset(g_channel_list, 0x0, CHANNEL_MAX_NUM); + + if (iwr->u.data.pointer && + iwr->u.data.length >= sizeof(struct iw_scan_req)) + { + req = (struct iw_scan_req *)iwr->u.data.pointer; + config->scan_type = (req->scan_type == IW_SCAN_TYPE_ACTIVE ? + WIFI_SCAN_TYPE_ACTIVE : WIFI_SCAN_TYPE_PASSIVE); + if (iwr->u.data.flags & IW_SCAN_THIS_ESSID && + req->essid_len < sizeof(target_ssid)) + { + /* Scan specific ESSID */ + + config->show_hidden = true; + config->bssid = NULL; + memcpy(&target_ssid[0], req->essid, req->essid_len); + config->ssid = &target_ssid[0]; + config->ssid[req->essid_len] = '\0'; + } + + if (iwr->u.data.flags & IW_SCAN_THIS_FREQ && + req->num_channels > 0) + { + /* Scan specific channels */ + + DEBUGASSERT(req->num_channels <= CHANNEL_MAX_NUM); + g_channel_num = req->num_channels; + if (req->num_channels == 1) + { + config->channel = req->channel_list[0].m; + } + else + { + for (i = 0; i < req->num_channels; i++) + { + g_channel_list[i] = req->channel_list[i].m; + } + } + } + + memset(target_mac, 0xff, MAC_LEN); + if (memcmp(req->bssid.sa_data, target_mac, MAC_LEN) != 0) + { + /* Scan specific bssid */ + + memcpy(target_mac, req->bssid.sa_data, MAC_LEN); + config->bssid = &target_mac[0]; + } + } + else + { + /* Default scan parameters */ + + wlinfo("INFO: Use default scan parameters\n"); + config->scan_type = WIFI_SCAN_TYPE_ACTIVE; /* Active scan */ + } + + esp_wifi_start(); + ret = esp_wifi_scan_start(config, false); + if (ret != OK) + { + wlerr("ERROR: Scan error, ret: %d\n", ret); + ret = ERROR; + } + else + { + /* Allocate buffer to store scan result */ + + if (priv->scan_result == NULL) + { + priv->scan_result = kmm_malloc(WIFI_SCAN_RESULT_SIZE); + if (priv->scan_result == NULL) + { + wlerr("ERROR: Cannot allocate result buffer\n"); + ret = -ENOMEM; + } + else + { + memset(priv->scan_result, 0x0, WIFI_SCAN_RESULT_SIZE); + } + } + } + + if (config) + { + kmm_free(config); + config = NULL; + } + + if (ret == OK) + { + wlinfo("INFO: start scan\n"); + g_scan_priv.scan_status = ESP_SCAN_RUN; + } + + return ret; +} + +/**************************************************************************** + * Name: esp_wifi_get_scan_results + * + * Description: + * Get scan result + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_get_scan_results(struct iwreq *iwr) +{ + int ret = OK; + static bool scan_block = false; + struct wifi_scan_result *priv = &g_scan_priv; + + if (g_scan_priv.scan_status == ESP_SCAN_RUN) + { + irqstate_t irqstate = enter_critical_section(); + if (!scan_block) + { + scan_block = true; + leave_critical_section(irqstate); + nxsem_tickwait(&priv->scan_signal, SEC2TICK(SCAN_TIME_SEC)); + scan_block = false; + } + else + { + leave_critical_section(irqstate); + ret = -EINVAL; + goto exit_failed; + } + } + else if (g_scan_priv.scan_status == ESP_SCAN_DISABLED) + { + ret = -EINVAL; + goto exit_failed; + } + + if ((iwr == NULL) || (g_scan_priv.scan_status != ESP_SCAN_DONE)) + { + ret = -EINVAL; + goto exit_failed; + } + + if (priv->scan_result == NULL) + { + /* Result have already been requested */ + + ret = OK; + iwr->u.data.length = 0; + goto exit_failed; + } + + if (priv->scan_result_size <= 0) + { + ret = OK; + iwr->u.data.length = 0; + goto exit_free_buffer; + } + + if (iwr->u.data.pointer == NULL || + iwr->u.data.length < priv->scan_result_size) + { + /* Stat request, return scan_result_size */ + + ret = -E2BIG; + iwr->u.data.pointer = NULL; + iwr->u.data.length = priv->scan_result_size; + return ret; + } + + /* Copy result to user buffer */ + + if (iwr->u.data.length > priv->scan_result_size) + { + iwr->u.data.length = priv->scan_result_size; + } + + memcpy(iwr->u.data.pointer, priv->scan_result, iwr->u.data.length); + +exit_free_buffer: + + /* Free scan result buffer */ + + kmm_free(priv->scan_result); + priv->scan_result = NULL; + priv->scan_result_size = 0; + g_scan_priv.scan_status = ESP_SCAN_DISABLED; + +exit_failed: + if (ret < 0) + { + iwr->u.data.length = 0; + } + + return ret; +} + +/**************************************************************************** + * Name: esp_wifi_scan_event_parse + * + * Description: + * Parse scan information + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp_wifi_scan_event_parse(void) +{ + struct wifi_scan_result *priv = &g_scan_priv; + wifi_ap_record_t *ap_list_buffer = NULL; + uint16_t bss_total = 0; + uint8_t bss_count = 0; + bool parse_done = false; + + if (priv->scan_status != ESP_SCAN_RUN) + { + return; + } + + esp_wifi_scan_get_ap_num(&bss_total); + if (bss_total == 0) + { + priv->scan_status = ESP_SCAN_DONE; + wlinfo("INFO: None AP is scanned\n"); + nxsem_post(&priv->scan_signal); + return; + } + + ap_list_buffer = kmm_calloc(bss_total, sizeof(wifi_ap_record_t)); + if (ap_list_buffer == NULL) + { + priv->scan_status = ESP_SCAN_DONE; + wlerr("ERROR: Failed to calloc buffer to print scan results"); + nxsem_post(&priv->scan_signal); + return; + } + + if (esp_wifi_scan_get_ap_records(&bss_total, + (wifi_ap_record_t *)ap_list_buffer) == OK) + { + struct iw_event *iwe; + unsigned int result_size; + size_t essid_len; + size_t essid_len_aligned; + bool is_target_channel = true; + int i; + + for (bss_count = 0; bss_count < bss_total; bss_count++) + { + if (g_channel_num > 1) + { + is_target_channel = false; + for (i = 0; i < g_channel_num; i++) + { + if (g_channel_list[i] == ap_list_buffer[bss_count].primary) + { + is_target_channel = true; + break; + } + } + } + else + { + is_target_channel = true; + } + + if (is_target_channel) + { + result_size = WIFI_SCAN_RESULT_SIZE - priv->scan_result_size; + + /* Copy BSSID */ + + if (result_size < ESP_IW_EVENT_SIZE(ap_addr)) + { + goto scan_result_full; + } + + iwe = (struct iw_event *) + &priv->scan_result[priv->scan_result_size]; + iwe->len = ESP_IW_EVENT_SIZE(ap_addr); + iwe->cmd = SIOCGIWAP; + memcpy(&iwe->u.ap_addr.sa_data, + ap_list_buffer[bss_count].bssid, + sizeof(ap_list_buffer[bss_count].bssid)); + iwe->u.ap_addr.sa_family = ARPHRD_ETHER; + priv->scan_result_size += ESP_IW_EVENT_SIZE(ap_addr); + result_size -= ESP_IW_EVENT_SIZE(ap_addr); + + /* Copy ESSID */ + + essid_len = MIN(strlen((const char *) + ap_list_buffer[bss_count].ssid), SSID_MAX_LEN); + essid_len_aligned = (essid_len + 3) & -4; + if (result_size < ESP_IW_EVENT_SIZE(essid) + essid_len_aligned) + { + goto scan_result_full; + } + + iwe = (struct iw_event *) + &priv->scan_result[priv->scan_result_size]; + iwe->len = ESP_IW_EVENT_SIZE(essid) + essid_len_aligned; + iwe->cmd = SIOCGIWESSID; + iwe->u.essid.flags = 0; + iwe->u.essid.length = essid_len; + + /* Special processing for iw_point, set offset + * in pointer field. + */ + + iwe->u.essid.pointer = (void *)sizeof(iwe->u.essid); + memcpy(&iwe->u.essid + 1, + ap_list_buffer[bss_count].ssid, essid_len); + + wlinfo("INFO: ssid %s\n", ap_list_buffer[bss_count].ssid); + + priv->scan_result_size += + ESP_IW_EVENT_SIZE(essid) + essid_len_aligned; + result_size -= ESP_IW_EVENT_SIZE(essid) + essid_len_aligned; + + /* Copy link quality info */ + + if (result_size < ESP_IW_EVENT_SIZE(qual)) + { + goto scan_result_full; + } + + iwe = (struct iw_event *) + &priv->scan_result[priv->scan_result_size]; + iwe->len = ESP_IW_EVENT_SIZE(qual); + iwe->cmd = IWEVQUAL; + iwe->u.qual.qual = 0x00; + + wlinfo("INFO: signal %d\n", ap_list_buffer[bss_count].rssi); + + iwe->u.qual.level = ap_list_buffer[bss_count].rssi; + iwe->u.qual.noise = 0x00; + iwe->u.qual.updated = IW_QUAL_DBM | IW_QUAL_ALL_UPDATED; + + priv->scan_result_size += ESP_IW_EVENT_SIZE(qual); + result_size -= ESP_IW_EVENT_SIZE(qual); + + /* Copy AP mode */ + + if (result_size < ESP_IW_EVENT_SIZE(mode)) + { + goto scan_result_full; + } + + iwe = (struct iw_event *) + &priv->scan_result[priv->scan_result_size]; + iwe->len = ESP_IW_EVENT_SIZE(mode); + iwe->cmd = SIOCGIWMODE; + iwe->u.mode = IW_MODE_MASTER; + priv->scan_result_size += ESP_IW_EVENT_SIZE(mode); + result_size -= ESP_IW_EVENT_SIZE(mode); + + /* Copy AP encryption mode */ + + if (result_size < ESP_IW_EVENT_SIZE(data)) + { + goto scan_result_full; + } + + iwe = (struct iw_event *) + &priv->scan_result[priv->scan_result_size]; + iwe->len = ESP_IW_EVENT_SIZE(data); + iwe->cmd = SIOCGIWENCODE; + iwe->u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; + iwe->u.data.length = 0; + iwe->u.essid.pointer = NULL; + + priv->scan_result_size += ESP_IW_EVENT_SIZE(data); + result_size -= ESP_IW_EVENT_SIZE(data); + + /* Copy AP channel */ + + if (result_size < ESP_IW_EVENT_SIZE(freq)) + { + goto scan_result_full; + } + + iwe = (struct iw_event *) + &priv->scan_result[priv->scan_result_size]; + iwe->len = ESP_IW_EVENT_SIZE(freq); + iwe->cmd = SIOCGIWFREQ; + iwe->u.freq.e = 0; + iwe->u.freq.m = ap_list_buffer[bss_count].primary; + + priv->scan_result_size += ESP_IW_EVENT_SIZE(freq); + result_size -= ESP_IW_EVENT_SIZE(freq); + } + } + + parse_done = true; + } + +scan_result_full: + + /* Continue instead of break to log dropped AP results */ + + if (!parse_done) + { + wlerr("ERROR: No more space in scan_result buffer\n"); + } + + if (ap_list_buffer) + { + kmm_free(ap_list_buffer); + ap_list_buffer = NULL; + } + + priv->scan_status = ESP_SCAN_DONE; + nxsem_post(&priv->scan_signal); +} diff --git a/arch/xtensa/src/common/espressif/esp_wifi_utils.h b/arch/xtensa/src/common/espressif/esp_wifi_utils.h new file mode 100644 index 00000000000..6b9f8530c55 --- /dev/null +++ b/arch/xtensa/src/common/espressif/esp_wifi_utils.h @@ -0,0 +1,104 @@ +/**************************************************************************** + * arch/xtensa/src/common/espressif/esp_wifi_utils.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#ifndef __ARCH_XTENSA_SRC_COMMON_ESPRESSIF_ESP_WIFI_UTILS_H +#define __ARCH_XTENSA_SRC_COMMON_ESPRESSIF_ESP_WIFI_UTILS_H + +#include +#include + +#ifndef __ASSEMBLY__ + +#include + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: esp_wifi_start_scan + * + * Description: + * Scan all available APs. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_start_scan(struct iwreq *iwr); + +/**************************************************************************** + * Name: esp_wifi_get_scan_results + * + * Description: + * Get scan result + * + * Input Parameters: + * req The argument of the ioctl cmd + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_get_scan_results(struct iwreq *iwr); + +/**************************************************************************** + * Name: esp_wifi_scan_event_parse + * + * Description: + * Parse scan information + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp_wifi_scan_event_parse(void); + +#ifdef __cplusplus +} +#endif +#undef EXTERN + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_XTENSA_SRC_COMMON_ESPRESSIF_ESP_WIFI_UTILS_H */ diff --git a/arch/xtensa/src/common/espressif/esp_wireless.c b/arch/xtensa/src/common/espressif/esp_wireless.c new file mode 100644 index 00000000000..42d1a3cf253 --- /dev/null +++ b/arch/xtensa/src/common/espressif/esp_wireless.c @@ -0,0 +1,1595 @@ +/**************************************************************************** + * arch/xtensa/src/common/espressif/esp_wireless.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include +#include +#include +#include + +#include "xtensa.h" +#ifdef CONFIG_ARCH_CHIP_ESP32 +#include "hardware/esp32_dport.h" +#include "hardware/esp32_emac.h" +#include "hardware/esp32_soc.h" +#include "esp32_irq.h" +#include "esp32_partition.h" +#elif CONFIG_ARCH_CHIP_ESP32S2 +#include "hardware/esp32s2_efuse.h" +#include "hardware/esp32s2_rtccntl.h" +#include "hardware/esp32s2_soc.h" +#include "hardware/esp32s2_syscon.h" +#include "hardware/esp32s2_system.h" +#include "esp32s2_irq.h" +/* #include "esp32s2_partition.h" */ +#elif CONFIG_ARCH_CHIP_ESP32S3 +#include "hardware/esp32s3_efuse.h" +#include "hardware/esp32s3_rtccntl.h" +#include "hardware/esp32s3_soc.h" +#include "hardware/esp32s3_syscon.h" +#include "hardware/esp32s3_system.h" +#include "esp32s3_irq.h" +#include "esp32s3_partition.h" +#endif + +#include "esp_private/phy.h" +#ifdef CONFIG_ESPRESSIF_WIFI +# include "esp_private/wifi.h" +# include "esp_wpa.h" +#endif + +#ifndef CONFIG_ARCH_CHIP_ESP32S2 +#include "private/esp_coexist_internal.h" +#endif +#include "periph_ctrl.h" +#include "esp_phy_init.h" +#include "phy_init_data.h" + +#include "esp_wireless.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Software Interrupt */ + +#ifdef CONFIG_ARCH_CHIP_ESP32 +# define SWI_IRQ ESP32_IRQ_CPU_CPU2 +# define SWI_PERIPH ESP32_PERIPH_CPU_CPU2 +# define esp_partition_read esp32_partition_read +# define esp_partition_write esp32_partition_write +# define esp_setup_irq esp32_setup_irq +# define esp_teardown_irq esp32_teardown_irq +#elif CONFIG_ARCH_CHIP_ESP32S2 +# define SWI_IRQ ESP32S2_IRQ_INT_FROM_CPU2 +# define SWI_PERIPH ESP32S2_PERIPH_INT_FROM_CPU2 +# define esp_partition_read esp32s2_partition_read +# define esp_partition_write esp32s2_partition_write +# define esp_setup_irq esp32s2_setup_irq +# define esp_teardown_irq esp32s2_teardown_irq +#elif CONFIG_ARCH_CHIP_ESP32S3 +# define SWI_IRQ ESP32S3_IRQ_INT_FROM_CPU2 +# define SWI_PERIPH ESP32S3_PERIPH_INT_FROM_CPU2 +# define esp_partition_read esp32s3_partition_read +# define esp_partition_write esp32s3_partition_write +# define rt_timer_create esp32s3_rt_timer_create +# define rt_timer_start esp32s3_rt_timer_start +# define rt_timer_stop esp32s3_rt_timer_stop +# define rt_timer_delete esp32s3_rt_timer_delete +# define esp_setup_irq esp32s3_setup_irq +# define esp_teardown_irq esp32s3_teardown_irq +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* Wireless Private Data */ + +struct esp_wireless_priv_s +{ + volatile int ref; /* Reference count */ + + int cpuint; /* CPU interrupt assigned to SWI */ + + struct list_node sc_list; /* Semaphore cache list */ + struct list_node qc_list; /* Queue cache list */ +#ifdef CONFIG_ARCH_CHIP_ESP32 + struct list_node qc_freelist; /* List of free queue cache structures */ +#endif +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static inline void phy_digital_regs_store(void); +static inline void phy_digital_regs_load(void); +static int esp_swi_irq(int irq, void *context, void *arg); +#ifdef CONFIG_ESP32_WIFI +static void esp_wifi_set_log_level(void); +#endif + +/**************************************************************************** + * Extern Functions declaration + ****************************************************************************/ + +extern uint8_t esp_crc8(const uint8_t *p, uint32_t len); +extern void phy_wakeup_init(void); +extern void phy_close_rf(void); +extern uint8_t phy_dig_reg_backup(bool init, uint32_t *regs); +extern int register_chipv7_phy(const esp_phy_init_data_t *init_data, + esp_phy_calibration_data_t *cal_data, + esp_phy_calibration_mode_t cal_mode); +extern uint32_t crc32_le(uint32_t crc, uint8_t const *buf, uint32_t len); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Wi-Fi sleep private data */ + +static uint32_t g_phy_clk_en_cnt; + +/* Reference count of enabling PHY */ + +static uint8_t g_phy_access_ref; + +/* Memory to store PHY digital registers */ + +static uint32_t *g_phy_digital_regs_mem = NULL; + +/* Indicate PHY is calibrated or not */ + +static bool g_is_phy_calibrated = false; + +/* Private data of the wireless common interface */ + +static struct esp_wireless_priv_s g_esp_wireless_priv; + +#ifdef CONFIG_ESPRESSIF_PHY_INIT_DATA_IN_PARTITION +static const char *phy_partion_label = "phy_init"; +#endif + +#ifdef CONFIG_ESPRESSIF_SUPPORT_MULTIPLE_PHY_INIT_DATA + +static phy_init_data_type_t g_phy_init_data_type; + +static phy_init_data_type_t g_current_apply_phy_init_data; + +static char g_phy_current_country[PHY_COUNTRY_CODE_LEN]; + +/* Whether it is a new bin */ + +static bool g_multiple_phy_init_data_bin; + +/* PHY init data type array */ + +static const char *g_phy_type[ESP_PHY_INIT_DATA_TYPE_NUMBER] = +{ + "DEFAULT", "SRRC", "FCC", "CE", "NCC", "KCC", "MIC", "IC", + "ACMA", "ANATEL", "ISED", "WPC", "OFCA", "IFETEL", "RCM" +}; + +/* Country and PHY init data type map */ + +static phy_country_to_bin_type_t g_country_code_map_type_table[] = +{ + {"01", ESP_PHY_INIT_DATA_TYPE_DEFAULT}, + {"AT", ESP_PHY_INIT_DATA_TYPE_CE}, + {"AU", ESP_PHY_INIT_DATA_TYPE_ACMA}, + {"BE", ESP_PHY_INIT_DATA_TYPE_CE}, + {"BG", ESP_PHY_INIT_DATA_TYPE_CE}, + {"BR", ESP_PHY_INIT_DATA_TYPE_ANATEL}, + {"CA", ESP_PHY_INIT_DATA_TYPE_ISED}, + {"CH", ESP_PHY_INIT_DATA_TYPE_CE}, + {"CN", ESP_PHY_INIT_DATA_TYPE_SRRC}, + {"CY", ESP_PHY_INIT_DATA_TYPE_CE}, + {"CZ", ESP_PHY_INIT_DATA_TYPE_CE}, + {"DE", ESP_PHY_INIT_DATA_TYPE_CE}, + {"DK", ESP_PHY_INIT_DATA_TYPE_CE}, + {"EE", ESP_PHY_INIT_DATA_TYPE_CE}, + {"ES", ESP_PHY_INIT_DATA_TYPE_CE}, + {"FI", ESP_PHY_INIT_DATA_TYPE_CE}, + {"FR", ESP_PHY_INIT_DATA_TYPE_CE}, + {"GB", ESP_PHY_INIT_DATA_TYPE_CE}, + {"GR", ESP_PHY_INIT_DATA_TYPE_CE}, + {"HK", ESP_PHY_INIT_DATA_TYPE_OFCA}, + {"HR", ESP_PHY_INIT_DATA_TYPE_CE}, + {"HU", ESP_PHY_INIT_DATA_TYPE_CE}, + {"IE", ESP_PHY_INIT_DATA_TYPE_CE}, + {"IN", ESP_PHY_INIT_DATA_TYPE_WPC}, + {"IS", ESP_PHY_INIT_DATA_TYPE_CE}, + {"IT", ESP_PHY_INIT_DATA_TYPE_CE}, + {"JP", ESP_PHY_INIT_DATA_TYPE_MIC}, + {"KR", ESP_PHY_INIT_DATA_TYPE_KCC}, + {"LI", ESP_PHY_INIT_DATA_TYPE_CE}, + {"LT", ESP_PHY_INIT_DATA_TYPE_CE}, + {"LU", ESP_PHY_INIT_DATA_TYPE_CE}, + {"LV", ESP_PHY_INIT_DATA_TYPE_CE}, + {"MT", ESP_PHY_INIT_DATA_TYPE_CE}, + {"MX", ESP_PHY_INIT_DATA_TYPE_IFETEL}, + {"NL", ESP_PHY_INIT_DATA_TYPE_CE}, + {"NO", ESP_PHY_INIT_DATA_TYPE_CE}, + {"NZ", ESP_PHY_INIT_DATA_TYPE_RCM}, + {"PL", ESP_PHY_INIT_DATA_TYPE_CE}, + {"PT", ESP_PHY_INIT_DATA_TYPE_CE}, + {"RO", ESP_PHY_INIT_DATA_TYPE_CE}, + {"SE", ESP_PHY_INIT_DATA_TYPE_CE}, + {"SI", ESP_PHY_INIT_DATA_TYPE_CE}, + {"SK", ESP_PHY_INIT_DATA_TYPE_CE}, + {"TW", ESP_PHY_INIT_DATA_TYPE_NCC}, + {"US", ESP_PHY_INIT_DATA_TYPE_FCC}, +}; + +#endif + +/* Callback function to update WiFi MAC time */ + +#ifdef CONFIG_ARCH_CHIP_ESP32 +wifi_mac_time_update_cb_t g_wifi_mac_time_update_cb = NULL; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: phy_digital_regs_store + * + * Description: + * Store PHY digital registers. + * + ****************************************************************************/ + +static inline void phy_digital_regs_store(void) +{ + if (g_phy_digital_regs_mem == NULL) + { + g_phy_digital_regs_mem = (uint32_t *) + kmm_malloc(SOC_PHY_DIG_REGS_MEM_SIZE); + } + + DEBUGASSERT(g_phy_digital_regs_mem != NULL); + + phy_dig_reg_backup(true, g_phy_digital_regs_mem); +} + +/**************************************************************************** + * Name: phy_digital_regs_load + * + * Description: + * Load PHY digital registers. + * + ****************************************************************************/ + +static inline void phy_digital_regs_load(void) +{ + if (g_phy_digital_regs_mem != NULL) + { + phy_dig_reg_backup(false, g_phy_digital_regs_mem); + } +} + +/**************************************************************************** + * Name: esp_swi_irq + * + * Description: + * Wireless software interrupt callback function. + * + * Parameters: + * cpuint - CPU interrupt index + * context - Context data from the ISR + * arg - NULL + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned on + * failure. + * + ****************************************************************************/ + +static int esp_swi_irq(int irq, void *context, void *arg) +{ + int i; + int ret; + struct esp_semcache_s *sc; + struct esp_semcache_s *sc_tmp; + struct esp_queuecache_s *qc; + struct esp_queuecache_s *qc_tmp; + struct esp_wireless_priv_s *priv = &g_esp_wireless_priv; + +#ifdef CONFIG_ARCH_CHIP_ESP32 + modifyreg32(DPORT_CPU_INTR_FROM_CPU_2_REG, DPORT_CPU_INTR_FROM_CPU_2, 0); +#else + modifyreg32(SYSTEM_CPU_INTR_FROM_CPU_2_REG, SYSTEM_CPU_INTR_FROM_CPU_2, 0); +#endif + + list_for_every_entry_safe(&priv->sc_list, sc, sc_tmp, + struct esp_semcache_s, node) + { + for (i = 0; i < sc->count; i++) + { + ret = nxsem_post(sc->sem); + if (ret < 0) + { + wlerr("ERROR: Failed to post sem ret=%d\n", ret); + } + } + + sc->count = 0; + list_delete(&sc->node); + } + + list_for_every_entry_safe(&priv->qc_list, qc, qc_tmp, + struct esp_queuecache_s, node) + { + ret = file_mq_send(qc->mq_ptr, (const char *)qc->buffer, qc->size, 0); + if (ret < 0) + { + wlerr("ERROR: Failed to send queue ret=%d\n", ret); + } + + list_delete(&qc->node); +#ifdef CONFIG_ARCH_CHIP_ESP32 + list_add_tail(&priv->qc_freelist, &qc->node); +#endif + } + + return OK; +} + +#ifdef CONFIG_ESPRESSIF_WIFI + +/**************************************************************************** + * Name: esp_wifi_set_log_level + * + * Description: + * Sets the log level for the ESP32 WiFi module based on preprocessor + * definitions. The log level can be verbose, warning, or error. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp_wifi_set_log_level(void) +{ + wifi_log_level_t wifi_log_level = WIFI_LOG_NONE; + + /* set WiFi log level */ + +#if defined(CONFIG_DEBUG_WIRELESS_INFO) + wifi_log_level = WIFI_LOG_VERBOSE; +#elif defined(CONFIG_DEBUG_WIRELESS_WARN) + wifi_log_level = WIFI_LOG_WARNING; +#elif defined(CONFIG_LOG_MAXIMUM_LEVEL) + wifi_log_level = WIFI_LOG_ERROR; +#endif + + esp_wifi_internal_set_log_level(wifi_log_level); +} +#endif /* CONFIG_ESPRESSIF_WIFI */ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: esp_wifi_to_errno + * + * Description: + * Transform from ESP Wi-Fi error code to NuttX error code + * + * Input Parameters: + * err - ESP Wi-Fi error code + * + * Returned Value: + * NuttX error code defined in errno.h + * + ****************************************************************************/ + +#ifndef CONFIG_ARCH_CHIP_ESP32S2 +int32_t esp_wifi_to_errno(int err) +{ + int ret; + + if (err < ESP_ERR_WIFI_BASE) + { + /* Unmask component error bits */ + + ret = err & 0xfff; + + switch (ret) + { + case ESP_OK: + ret = OK; + break; + case ESP_ERR_NO_MEM: + ret = -ENOMEM; + break; + + case ESP_ERR_INVALID_ARG: + ret = -EINVAL; + break; + + case ESP_ERR_INVALID_STATE: + ret = -EIO; + break; + + case ESP_ERR_INVALID_SIZE: + ret = -EINVAL; + break; + + case ESP_ERR_NOT_FOUND: + ret = -ENOSYS; + break; + + case ESP_ERR_NOT_SUPPORTED: + ret = -ENOSYS; + break; + + case ESP_ERR_TIMEOUT: + ret = -ETIMEDOUT; + break; + + case ESP_ERR_INVALID_MAC: + ret = -EINVAL; + break; + + default: + ret = ERROR; + break; + } + } + else + { + ret = ERROR; + } + + if (ret != OK) + { + wlerr("ERROR: %s\n", esp_err_to_name(err)); + } + + return ret; +} +#endif + +/**************************************************************************** + * Functions needed by libphy.a + ****************************************************************************/ + +/**************************************************************************** + * Name: esp_dport_access_reg_read + * + * Description: + * Read register value safely in SMP + * + * Input Parameters: + * reg - Register address + * + * Returned Value: + * Register value + * + ****************************************************************************/ + +uint32_t IRAM_ATTR esp_dport_access_reg_read(uint32_t reg) +{ + return getreg32(reg); +} + +/**************************************************************************** + * Name: phy_printf + * + * Description: + * Output format string and its arguments + * + * Input Parameters: + * format - format string + * + * Returned Value: + * 0 + * + ****************************************************************************/ + +int phy_printf(const char *format, ...) +{ +#ifdef CONFIG_DEBUG_WIRELESS_INFO + va_list arg; + + va_start(arg, format); + vsyslog(LOG_INFO, format, arg); + va_end(arg); +#endif + + return 0; +} + +#ifdef CONFIG_ESPRESSIF_SUPPORT_MULTIPLE_PHY_INIT_DATA + +/**************************************************************************** + * Name: phy_crc_check + * + * Description: + * Check the checksum value of data + * + * Input Parameters: + * data - Data buffer pointer + * length - Data length + * checksum - Checksum pointer + * + * Returned Value: + * OK on success; a negated errno on failure + * + ****************************************************************************/ + +static int phy_crc_check(uint8_t *data, const uint8_t *checksum, + size_t length) +{ + uint32_t crc_data = crc32_le(0, data, length); + uint32_t crc_size_conversion = HTONL(crc_data); + uint32_t tmp_crc = checksum[0] | (checksum[1] << 8) | (checksum[2] << 16) | + (checksum[3] << 24); + if (crc_size_conversion != tmp_crc) + { + return ERROR; + } + + return OK; +} + +/**************************************************************************** + * Name: phy_find_bin_type_according_country + * + * Description: + * Find the PHY initialization data type according to country code + * + * Input Parameters: + * country - Country code pointer + * + * Returned Value: + * PHY initialization data type + * + ****************************************************************************/ + +static uint8_t phy_find_bin_type_according_country(const char *country) +{ + uint8_t i; + uint8_t phy_init_data_type; + uint8_t num = nitems(g_country_code_map_type_table); + for (i = 0; i < num; i++) + { + if (memcmp(country, g_country_code_map_type_table[i].cc, + sizeof(g_phy_current_country)) == 0) + { + phy_init_data_type = g_country_code_map_type_table[i].type; + wlinfo("Current country is %c%c, PHY init data type is %s\n", + g_country_code_map_type_table[i].cc[0], + g_country_code_map_type_table[i].cc[1], + g_phy_type[g_country_code_map_type_table[i].type]); + break; + } + } + + if (i == num) + { + phy_init_data_type = ESP_PHY_INIT_DATA_TYPE_DEFAULT; + wlerr("Use the default certification code beacuse %c%c doesn't " + "have a certificate\n", country[0], country[1]); + } + + return phy_init_data_type; +} + +/**************************************************************************** + * Name: phy_find_bin_data_according_type + * + * Description: + * Find the PHY initialization data according to PHY init data type + * + * Input Parameters: + * output_data - Output data buffer pointer + * control_info - PHY init data control infomation + * input_data - Input data buffer pointer + * init_data_type - PHY init data type + * + * Returned Value: + * OK on success; a negated errno on failure + * + ****************************************************************************/ + +static int phy_find_bin_data_according_type(uint8_t *output_data, + const phy_control_info_data_t *control_info, + const esp_phy_init_data_t *input_data, + phy_init_data_type_t init_data_type) +{ + int i; + for (i = 0; i < control_info->number; i++) + { + if (init_data_type == *((uint8_t *)(input_data + i) + + PHY_INIT_DATA_TYPE_OFFSET)) + { + memcpy(output_data + sizeof(phy_init_magic_pre), + (input_data + i), sizeof(esp_phy_init_data_t)); + break; + } + } + + if (i == control_info->number) + { + return ERROR; + } + + return OK; +} + +/**************************************************************************** + * Name: phy_get_multiple_init_data + * + * Description: + * Get multiple PHY init data according to PHY init data type + * + * Input Parameters: + * data - Data buffer pointer + * length - Data length + * init_data_type - PHY init data type + * + * Returned Value: + * OK on success; a negated errno on failure + * + ****************************************************************************/ + +static int phy_get_multiple_init_data(uint8_t *data, size_t length, + phy_init_data_type_t init_data_type) +{ + phy_control_info_data_t *control_info = (phy_control_info_data_t *) + kmm_malloc(sizeof(phy_control_info_data_t)); + if (control_info == NULL) + { + wlerr("ERROR: Failed to allocate memory for\ + PHY init data control info\n"); + return -ENOMEM; + } + + int ret = esp_partition_read(phy_partion_label, + length, + control_info, + sizeof(phy_control_info_data_t)); + if (ret != OK) + { + kmm_free(control_info); + wlerr("ERROR: Failed to read PHY control info data partition\n"); + return ret; + } + + if ((control_info->check_algorithm) == PHY_CRC_ALGORITHM) + { + ret = phy_crc_check(control_info->multiple_bin_checksum, + control_info->control_info_checksum, + sizeof(phy_control_info_data_t) - + sizeof(control_info->control_info_checksum)); + if (ret != OK) + { + kmm_free(control_info); + wlerr("ERROR: PHY init data control info check error\n"); + return ret; + } + } + else + { + kmm_free(control_info); + wlerr("ERROR: Check algorithm not CRC, PHY init data update failed\n"); + return ERROR; + } + + uint8_t *init_data_multiple = (uint8_t *) + kmm_malloc(sizeof(esp_phy_init_data_t) * control_info->number); + if (init_data_multiple == NULL) + { + kmm_free(control_info); + wlerr("ERROR: Failed to allocate memory for PHY init data\n"); + return -ENOMEM; + } + + ret = esp_partition_read(phy_partion_label, length + + sizeof(phy_control_info_data_t), init_data_multiple, + sizeof(esp_phy_init_data_t) * control_info->number); + if (ret != OK) + { + kmm_free(init_data_multiple); + kmm_free(control_info); + wlerr("ERROR: Failed to read PHY init data multiple bin partition\n"); + return ret; + } + + if ((control_info->check_algorithm) == PHY_CRC_ALGORITHM) + { + ret = phy_crc_check(init_data_multiple, + control_info->multiple_bin_checksum, + sizeof(esp_phy_init_data_t) * control_info->number); + if (ret != OK) + { + kmm_free(init_data_multiple); + kmm_free(control_info); + wlerr("ERROR: PHY init data multiple bin check error\n"); + return ret; + } + } + else + { + kmm_free(init_data_multiple); + kmm_free(control_info); + wlerr("ERROR: Check algorithm not CRC, PHY init data update failed\n"); + return ERROR; + } + + ret = phy_find_bin_data_according_type(data, control_info, + (const esp_phy_init_data_t *)init_data_multiple, init_data_type); + if (ret != OK) + { + wlerr("ERROR: %s has not been certified, use DEFAULT PHY init data\n", + g_phy_type[init_data_type]); + g_phy_init_data_type = ESP_PHY_INIT_DATA_TYPE_DEFAULT; + } + else + { + g_phy_init_data_type = init_data_type; + } + + kmm_free(init_data_multiple); + kmm_free(control_info); + return OK; +} + +/**************************************************************************** + * Name: phy_update_init_data + * + * Description: + * Update PHY init data according to PHY init data type + * + * Input Parameters: + * init_data_type - PHY init data type + * + * Returned Value: + * OK on success; a negated errno on failure + * + ****************************************************************************/ + +static int phy_update_init_data(phy_init_data_type_t init_data_type) +{ + int ret; + size_t length = sizeof(phy_init_magic_pre) + + sizeof(esp_phy_init_data_t) + sizeof(phy_init_magic_post); + uint8_t *init_data_store = kmm_malloc(length); + if (init_data_store == NULL) + { + wlerr("ERROR: Failed to allocate memory for updated country code " + "PHY init data\n"); + return -ENOMEM; + } + + ret = esp_partition_read(phy_partion_label, 0, init_data_store, + length); + if (ret != OK) + { + kmm_free(init_data_store); + wlerr("ERROR: Failed to read updated country code PHY data\n"); + return ret; + } + + if (memcmp(init_data_store, PHY_INIT_MAGIC, + sizeof(phy_init_magic_pre)) != 0 || + memcmp(init_data_store + length - sizeof(phy_init_magic_post), + PHY_INIT_MAGIC, sizeof(phy_init_magic_post)) != 0) + { + kmm_free(init_data_store); + wlerr("ERROR: Failed to validate updated country code PHY data\n"); + return ERROR; + } + + /* find init data bin according init data type */ + + if (init_data_type != ESP_PHY_INIT_DATA_TYPE_DEFAULT) + { + ret = phy_get_multiple_init_data(init_data_store, length, + init_data_type); + if (ret != OK) + { + kmm_free(init_data_store); +#ifdef CONFIG_ESPRESSIF_PHY_INIT_DATA_ERROR + abort(); +#else + return ret; +#endif + } + } + else + { + g_phy_init_data_type = ESP_PHY_INIT_DATA_TYPE_DEFAULT; + } + + if (g_current_apply_phy_init_data != g_phy_init_data_type) + { + ret = esp_phy_apply_phy_init_data(init_data_store + + sizeof(phy_init_magic_pre)); + if (ret != OK) + { + wlerr("ERROR: PHY init data failed to load\n"); + kmm_free(init_data_store); + return ret; + } + + wlinfo("PHY init data type updated from %s to %s\n", + g_phy_type[g_current_apply_phy_init_data], + g_phy_type[g_phy_init_data_type]); + g_current_apply_phy_init_data = g_phy_init_data_type; + } + + kmm_free(init_data_store); + return OK; +} + +#endif + +#ifdef CONFIG_ESPRESSIF_PHY_INIT_DATA_IN_PARTITION + +/**************************************************************************** + * Name: esp_phy_get_init_data + * + * Description: + * Get PHY init data + * + * Input Parameters: + * None + * + * Returned Value: + * Pointer to PHY init data structure + * + ****************************************************************************/ + +const esp_phy_init_data_t *esp_phy_get_init_data(void) +{ + int ret; + size_t length = sizeof(phy_init_magic_pre) + + sizeof(esp_phy_init_data_t) + sizeof(phy_init_magic_post); + uint8_t *init_data_store = kmm_malloc(length); + if (init_data_store == NULL) + { + wlerr("ERROR: Failed to allocate memory for PHY init data\n"); + return NULL; + } + + ret = esp_partition_read(phy_partion_label, 0, init_data_store, + length); + if (ret != OK) + { + wlerr("ERROR: Failed to get read data from MTD\n"); + kmm_free(init_data_store); + return NULL; + } + + if (memcmp(init_data_store, PHY_INIT_MAGIC, sizeof(phy_init_magic_pre)) + != 0 || memcmp(init_data_store + length - sizeof(phy_init_magic_post), + PHY_INIT_MAGIC, sizeof(phy_init_magic_post)) != 0) + { +#ifdef CONFIG_ESPRESSIF_PHY_DEFAULT_INIT_IF_INVALID + wlerr("ERROR: Failed to validate PHY data partition, restoring " + "default data into flash..."); + memcpy(init_data_store, PHY_INIT_MAGIC, sizeof(phy_init_magic_pre)); + memcpy(init_data_store + sizeof(phy_init_magic_pre), + &phy_init_data, sizeof(phy_init_data)); + memcpy(init_data_store + sizeof(phy_init_magic_pre) + + sizeof(phy_init_data), PHY_INIT_MAGIC, + sizeof(phy_init_magic_post)); + DEBUGASSERT(memcmp(init_data_store, PHY_INIT_MAGIC, + sizeof(phy_init_magic_pre)) == 0); + DEBUGASSERT(memcmp(init_data_store + length - + sizeof(phy_init_magic_post), PHY_INIT_MAGIC, + sizeof(phy_init_magic_post)) == 0); + + /* write default data */ + + ret = esp_partition_write(phy_partion_label, 0, init_data_store, + length); + if (ret != OK) + { + wlerr("ERROR: Failed to write default PHY data partition\n"); + kmm_free(init_data_store); + return NULL; + } +#else /* CONFIG_ESPRESSIF_PHY_DEFAULT_INIT_IF_INVALID */ + wlerr("ERROR: Failed to validate PHY data partition\n"); + kmm_free(init_data_store); + return NULL; +#endif + } + +#ifdef CONFIG_ESPRESSIF_SUPPORT_MULTIPLE_PHY_INIT_DATA + if (*(init_data_store + (sizeof(phy_init_magic_pre) + + PHY_SUPPORT_MULTIPLE_BIN_OFFSET))) + { + g_multiple_phy_init_data_bin = true; + wlinfo("Support multiple PHY init data bins\n"); + } + else + { + wlinfo("Does not support multiple PHY init data bins\n"); + } +#endif + + wlinfo("PHY data partition validated\n"); + return (const esp_phy_init_data_t *) + (init_data_store + sizeof(phy_init_magic_pre)); +} + +/**************************************************************************** + * Name: esp_phy_release_init_data + * + * Description: + * Release PHY init data + * + * Input Parameters: + * init_data - Pointer to PHY init data structure + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp_phy_release_init_data(const esp_phy_init_data_t *init_data) +{ + kmm_free((uint8_t *)init_data - sizeof(phy_init_magic_pre)); +} + +#else /* CONFIG_ESPRESSIF_PHY_INIT_DATA_IN_PARTITION */ + +/**************************************************************************** + * Name: esp_phy_get_init_data + * + * Description: + * Get PHY init data + * + * Input Parameters: + * None + * + * Returned Value: + * Pointer to PHY init data structure + * + ****************************************************************************/ + +const esp_phy_init_data_t *esp_phy_get_init_data(void) +{ + wlinfo("Loading PHY init data from application binary\n"); + return &phy_init_data; +} + +/**************************************************************************** + * Name: esp_phy_release_init_data + * + * Description: + * Release PHY init data + * + * Input Parameters: + * init_data - Pointer to PHY init data structure + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp_phy_release_init_data(const esp_phy_init_data_t *init_data) +{ +} +#endif + +/**************************************************************************** + * Name: esp_phy_update_country_info + * + * Description: + * Update PHY init data according to country code + * + * Input Parameters: + * country - PHY init data type + * + * Returned Value: + * OK on success; a negated errno on failure + * + ****************************************************************************/ + +int esp_phy_update_country_info(const char *country) +{ +#ifdef CONFIG_ESPRESSIF_SUPPORT_MULTIPLE_PHY_INIT_DATA + uint8_t phy_init_data_type_map = 0; + if (memcmp(country, g_phy_current_country, sizeof(g_phy_current_country)) + == 0) + { + return OK; + } + + memcpy(g_phy_current_country, country, sizeof(g_phy_current_country)); + if (!g_multiple_phy_init_data_bin) + { + wlerr("ERROR: Does not support multiple PHY init data bins\n"); + return ERROR; + } + + phy_init_data_type_map = phy_find_bin_type_according_country(country); + if (phy_init_data_type_map == g_phy_init_data_type) + { + return OK; + } + + int ret = phy_update_init_data(phy_init_data_type_map); + if (ret != OK) + { + wlerr("ERROR: Failed to update PHY init data\n"); + return ret; + } +#endif + + return OK; +} + +/**************************************************************************** + * Name: esp_timer_create + * + * Description: + * Create timer with given arguments + * + * Input Parameters: + * create_args - Timer arguments data pointer + * out_handle - Timer handle pointer + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int32_t esp_timer_create(const esp_timer_create_args_t *create_args, + esp_timer_handle_t *out_handle) +{ + int ret; + struct rt_timer_args_s rt_timer_args; + struct rt_timer_s *rt_timer; + + rt_timer_args.arg = create_args->arg; + rt_timer_args.callback = create_args->callback; + + ret = rt_timer_create(&rt_timer_args, &rt_timer); + if (ret) + { + wlerr("Failed to create rt_timer error=%d\n", ret); + return ret; + } + + *out_handle = (esp_timer_handle_t)rt_timer; + + return 0; +} + +/**************************************************************************** + * Name: esp_timer_start_once + * + * Description: + * Start timer with one shot mode + * + * Input Parameters: + * timer - Timer handle pointer + * timeout_us - Timeout value by micro second + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int32_t esp_timer_start_once(esp_timer_handle_t timer, uint64_t timeout_us) +{ + struct rt_timer_s *rt_timer = (struct rt_timer_s *)timer; + + rt_timer_start(rt_timer, timeout_us, false); + + return 0; +} + +/**************************************************************************** + * Name: esp_timer_start_periodic + * + * Description: + * Start timer with periodic mode + * + * Input Parameters: + * timer - Timer handle pointer + * period - Timeout value by micro second + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int32_t esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t period) +{ + struct rt_timer_s *rt_timer = (struct rt_timer_s *)timer; + + rt_timer_start(rt_timer, period, true); + + return 0; +} + +/**************************************************************************** + * Name: esp_timer_stop + * + * Description: + * Stop timer + * + * Input Parameters: + * timer - Timer handle pointer + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int32_t esp_timer_stop(esp_timer_handle_t timer) +{ + struct rt_timer_s *rt_timer = (struct rt_timer_s *)timer; + + rt_timer_stop(rt_timer); + + return 0; +} + +/**************************************************************************** + * Name: esp_timer_delete + * + * Description: + * Delete timer and free resource + * + * Input Parameters: + * timer - Timer handle pointer + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int32_t esp_timer_delete(esp_timer_handle_t timer) +{ + struct rt_timer_s *rt_timer = (struct rt_timer_s *)timer; + + rt_timer_delete(rt_timer); + + return 0; +} + +/**************************************************************************** + * Name: esp_init_semcache + * + * Description: + * Initialize semaphore cache. + * + * Parameters: + * sc - Semaphore cache data pointer + * sem - Semaphore data pointer + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void esp_init_semcache(struct esp_semcache_s *sc, sem_t *sem) +{ + sc->sem = sem; + sc->count = 0; + list_initialize(&sc->node); +} + +/**************************************************************************** + * Name: esp_post_semcache + * + * Description: + * Store posting semaphore action into semaphore cache. + * + * Parameters: + * sc - Semaphore cache data pointer + * + * Returned Value: + * None. + * + ****************************************************************************/ + +IRAM_ATTR void esp_post_semcache(struct esp_semcache_s *sc) +{ + struct esp_wireless_priv_s *priv = &g_esp_wireless_priv; + + if (!sc->count) + { + list_add_tail(&priv->sc_list, &sc->node); + } + + sc->count++; + + /* Enable CPU 2 interrupt. This will generate an IRQ as soon as non-IRAM + * are (re)enabled. + */ + +#ifdef CONFIG_ARCH_CHIP_ESP32 + modifyreg32(DPORT_CPU_INTR_FROM_CPU_2_REG, 0, DPORT_CPU_INTR_FROM_CPU_2); +#else + modifyreg32(SYSTEM_CPU_INTR_FROM_CPU_2_REG, 0, SYSTEM_CPU_INTR_FROM_CPU_2); +#endif +} + +/**************************************************************************** + * Name: esp_init_queuecache + * + * Description: + * Initialize queue cache. + * + * Parameters: + * qc - Queue cache data pointer + * mq_ptr - Queue data pointer + * buffer - Queue cache buffer pointer + * len - Queue cache max length (ESP32 only) + * size - Queue cache buffer size + * + * Returned Value: + * None. + * + ****************************************************************************/ + +#ifdef CONFIG_ARCH_CHIP_ESP32 +void esp_init_queuecache(struct esp_queuecache_s *qc, + struct file *mq_ptr, + uint8_t *buffer, + size_t len, + size_t size) +{ + struct esp_wireless_priv_s *priv = &g_esp_wireless_priv; + int i; + + for (i = 0; i < len; i++) + { + qc[i].mq_ptr = mq_ptr; + qc[i].size = size; + qc[i].buffer = buffer; + list_initialize(&qc[i].node); + + list_add_tail(&priv->qc_freelist, &qc[i].node); + } +} +#else +void esp_init_queuecache(struct esp_queuecache_s *qc, + struct file *mq_ptr, + uint8_t *buffer, + size_t size) +{ + qc->mq_ptr = mq_ptr; + qc->size = size; + qc->buffer = buffer; + list_initialize(&qc->node); +} +#endif + +/**************************************************************************** + * Name: esp_send_queuecache + * + * Description: + * Store posting queue action and data into queue cache. + * + * Parameters: + * qc - Queue cache data pointer + * buffer - Data buffer + * size - Buffer size + * + * Returned Value: + * None. + * + ****************************************************************************/ + +#ifdef CONFIG_ARCH_CHIP_ESP32 +IRAM_ATTR void esp_send_queuecache(void *queue, uint8_t *buffer, int size) +{ + struct esp_wireless_priv_s *priv = &g_esp_wireless_priv; + struct esp_queuecache_s *msg; + irqstate_t flags; + + flags = enter_critical_section(); + + msg = (struct esp_queuecache_s *)list_remove_head(&priv->qc_freelist); + DEBUGASSERT(msg != NULL); + + DEBUGASSERT(msg->size == size); + DEBUGASSERT(msg->mq_ptr == queue); + + memcpy(msg->buffer, buffer, size); + + list_add_tail(&priv->qc_list, &msg->node); + + leave_critical_section(flags); + + /* Enable CPU 2 interrupt. This will generate an IRQ as soon as non-IRAM + * are (re)enabled. + */ + + modifyreg32(DPORT_CPU_INTR_FROM_CPU_2_REG, 0, DPORT_CPU_INTR_FROM_CPU_2); +} +#else +IRAM_ATTR void esp_send_queuecache(struct esp_queuecache_s *qc, + uint8_t *buffer, + int size) +{ + struct esp_wireless_priv_s *priv = &g_esp_wireless_priv; + + DEBUGASSERT(qc->size == size); + + list_add_tail(&priv->qc_list, &qc->node); + memcpy(qc->buffer, buffer, size); + + /* Enable CPU 0 interrupt. This will generate an IRQ as soon as non-IRAM + * are (re)enabled. + */ + + modifyreg32(SYSTEM_CPU_INTR_FROM_CPU_2_REG, 0, SYSTEM_CPU_INTR_FROM_CPU_2); +} +#endif + +/**************************************************************************** + * Name: esp_wireless_init + * + * Description: + * Initialize ESP32 wireless common components for both BT and Wi-Fi. + * + * Parameters: + * None + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned on + * failure. + * + ****************************************************************************/ + +int esp_wireless_init(void) +{ + int ret; + irqstate_t flags; + struct esp_wireless_priv_s *priv = &g_esp_wireless_priv; + + flags = enter_critical_section(); + if (priv->ref != 0) + { + priv->ref++; + leave_critical_section(flags); + return OK; + } + +#ifdef CONFIG_ARCH_CHIP_ESP32 + priv->cpuint = esp_setup_irq(0, SWI_PERIPH, 1, ESP32_CPUINT_LEVEL); +#elif CONFIG_ARCH_CHIP_ESP32S2 + priv->cpuint = esp_setup_irq(SWI_PERIPH, ESP32S2_INT_PRIO_DEF, 0); +#elif CONFIG_ARCH_CHIP_ESP32S3 + priv->cpuint = esp_setup_irq(0, SWI_PERIPH, ESP32S3_INT_PRIO_DEF, 0); +#endif + if (priv->cpuint < 0) + { + /* Failed to allocate a CPU interrupt of this type. */ + + wlerr("ERROR: Failed to attach IRQ ret=%d\n", ret); + ret = priv->cpuint; + leave_critical_section(flags); + + return ret; + } + + ret = irq_attach(SWI_IRQ, esp_swi_irq, NULL); + if (ret < 0) + { +#ifdef CONFIG_ARCH_CHIP_ESP32 + esp_teardown_irq(0, SWI_PERIPH, priv->cpuint); +#elif CONFIG_ARCH_CHIP_ESP32S2 + esp_teardown_irq(SWI_PERIPH, priv->cpuint); +#elif CONFIG_ARCH_CHIP_ESP32S3 + esp_teardown_irq(0, SWI_PERIPH, priv->cpuint); +#endif + leave_critical_section(flags); + wlerr("ERROR: Failed to attach IRQ ret=%d\n", ret); + + return ret; + } + + list_initialize(&priv->sc_list); + list_initialize(&priv->qc_list); +#ifdef CONFIG_ARCH_CHIP_ESP32 + list_initialize(&priv->qc_freelist); +#endif + up_enable_irq(SWI_IRQ); + + priv->ref++; + + leave_critical_section(flags); + + return OK; +} + +/**************************************************************************** + * Name: esp_wireless_deinit + * + * Description: + * De-initialize ESP32 wireless common components. + * + * Parameters: + * None + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned on + * failure. + * + ****************************************************************************/ + +int esp_wireless_deinit(void) +{ + irqstate_t flags; + struct esp_wireless_priv_s *priv = &g_esp_wireless_priv; + + flags = enter_critical_section(); + + if (priv->ref > 0) + { + priv->ref--; + if (priv->ref == 0) + { + up_disable_irq(SWI_IRQ); + irq_detach(SWI_IRQ); +#ifdef CONFIG_ARCH_CHIP_ESP32 + esp_teardown_irq(0, SWI_PERIPH, priv->cpuint); +#elif CONFIG_ARCH_CHIP_ESP32S2 + esp_teardown_irq(SWI_PERIPH, priv->cpuint); +#elif CONFIG_ARCH_CHIP_ESP32S3 + esp_teardown_irq(0, SWI_PERIPH, priv->cpuint); +#endif + } + } + + leave_critical_section(flags); + + return OK; +} + +#ifdef CONFIG_ESPRESSIF_WIFI + +/**************************************************************************** + * Name: esp_wifi_init + * + * Description: + * Initialize Wi-Fi + * + * Input Parameters: + * config - Initialization config parameters + * + * Returned Value: + * 0 if success or others if fail + * + ****************************************************************************/ + +int32_t esp_wifi_init(const wifi_init_config_t *config) +{ + int32_t ret; + +#ifdef CONFIG_ARCH_CHIP_ESP32S3 + uint32_t min_active_time_us = + CONFIG_ESP_WIFI_SLP_DEFAULT_MIN_ACTIVE_TIME * 1000; + uint32_t keep_alive_time_us = + CONFIG_ESP_WIFI_SLP_DEFAULT_MAX_ACTIVE_TIME * 1000 * 1000; + uint32_t wait_broadcast_data_time_us = + CONFIG_ESP_WIFI_SLP_DEFAULT_WAIT_BROADCAST_DATA_TIME * 1000; + + esp_wifi_set_sleep_min_active_time(min_active_time_us); + esp_wifi_set_keep_alive_time(keep_alive_time_us); + esp_wifi_set_sleep_wait_broadcast_data_time(wait_broadcast_data_time_us); +#endif + +#if defined(CONFIG_ESP32S3_WIFI_BT_COEXIST) || \ + defined(CONFIG_ESP32_WIFI_BT_COEXIST) + ret = coex_init(); + if (ret) + { + wlerr("ERROR: Failed to initialize coex error=%d\n", ret); + return ret; + } +#endif + + /* WARN: Verify if power domain should go on before or after BT coexist */ + + esp_wifi_power_domain_on(); + + esp_wifi_set_log_level(); + + ret = esp_wifi_init_internal(config); + if (ret) + { + wlerr("Failed to initialize Wi-Fi error=%d\n", ret); + return ret; + } + +#if defined(CONFIG_MAC_BB_P) && defined(CONFIG_ARCH_CHIP_ESP32) + esp_mac_bb_pd_mem_init(); + esp_wifi_internal_set_mac_sleep(true); +#endif + esp_phy_modem_init(); + +#ifdef CONFIG_ARCH_CHIP_ESP32 + g_wifi_mac_time_update_cb = esp_wifi_internal_update_mac_time; +#endif + + ret = esp_supplicant_init(); + if (ret) + { + wlerr("Failed to initialize WPA supplicant error=%d\n", ret); + esp_wifi_deinit_internal(); + return ret; + } + + return 0; +} + +/**************************************************************************** + * Name: esp_wifi_deinit + * + * Description: + * Deinitialize Wi-Fi and free resource + * + * Input Parameters: + * None + * + * Returned Value: + * 0 if success or others if fail + * + ****************************************************************************/ + +int32_t esp_wifi_deinit(void) +{ + int ret; + + ret = esp_supplicant_deinit(); + if (ret) + { + wlerr("Failed to deinitialize supplicant\n"); + return ret; + } + + ret = esp_wifi_deinit_internal(); + if (ret != 0) + { + wlerr("Failed to deinitialize Wi-Fi\n"); + return ret; + } + + return ret; +} +#endif /* CONFIG_ESPRESSIF_WIFI */ diff --git a/arch/xtensa/src/common/espressif/esp_wireless.h b/arch/xtensa/src/common/espressif/esp_wireless.h new file mode 100644 index 00000000000..b3820dc08e8 --- /dev/null +++ b/arch/xtensa/src/common/espressif/esp_wireless.h @@ -0,0 +1,403 @@ +/**************************************************************************** + * arch/xtensa/src/common/espressif/esp_wireless.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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 __ARCH_XTENSA_SRC_COMMON_ESPRESSIF_ESP_WIRELESS_H +#define __ARCH_XTENSA_SRC_COMMON_ESPRESSIF_ESP_WIRELESS_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ +#include +#include +#include + +#include +#include + +#ifdef CONFIG_ARCH_CHIP_ESP32 +#include "xtensa_attr.h" +#include "esp32_rt_timer.h" +#elif CONFIG_ARCH_CHIP_ESP32S2 +#include "esp_attr.h" +#include "esp32s2_rt_timer.h" +#elif CONFIG_ARCH_CHIP_ESP32S3 +#include "esp_attr.h" +#include "esp32s3_rt_timer.h" +#endif + +#include "esp_log.h" +#include "esp_mac.h" +#include "esp_private/phy.h" +#include "esp_private/wifi.h" +#include "esp_random.h" +#include "esp_timer.h" +#include "rom/ets_sys.h" +#include "soc/soc_caps.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Note: Don't remove these definitions, they are needed by the 3rdparty IDF + * headers + */ + +#ifdef CONFIG_ARCH_CHIP_ESP32 +# ifdef CONFIG_ESP32_SUPPORT_MULTIPLE_PHY_INIT_DATA +# undef CONFIG_ESP32_SUPPORT_MULTIPLE_PHY_INIT_DATA_BIN +# define CONFIG_ESP32_SUPPORT_MULTIPLE_PHY_INIT_DATA_BIN 1 +# endif +# define SOC_COEX_HW_PTI 0 +#endif + +#define CONFIG_MAC_BB_PD (0) +#define MAC_LEN (6) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Semaphore Cache Data */ + +struct esp_semcache_s +{ + struct list_node node; + + sem_t *sem; + uint32_t count; +}; + +/* Queue Cache Data */ + +struct esp_queuecache_s +{ + struct list_node node; + + struct file *mq_ptr; + size_t size; + uint8_t *buffer; +}; + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nuttx_err_to_freertos + * + * Description: + * Transform from Nuttx OS error code to FreeRTOS's pdTRUE or pdFALSE. + * + * Input Parameters: + * ret - NuttX error code + * + * Returned Value: + * Wi-Fi adapter error code + * + ****************************************************************************/ + +#ifndef CONFIG_ARCH_CHIP_ESP32S2 +static inline int32_t nuttx_err_to_freertos(int ret) +{ + return ret >= 0; +} +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: esp_wifi_to_errno + * + * Description: + * Transform from ESP Wi-Fi error code to NuttX error code + * + * Input Parameters: + * err - ESP Wi-Fi error code + * + * Returned Value: + * NuttX error code defined in errno.h + * + ****************************************************************************/ + +#ifndef CONFIG_ARCH_CHIP_ESP32S2 +int32_t esp_wifi_to_errno(int err); +#endif + +/**************************************************************************** + * Functions needed by libphy.a + ****************************************************************************/ + +/**************************************************************************** + * Name: esp_dport_access_reg_read + * + * Description: + * Read register value safely in SMP + * + * Input Parameters: + * reg - Register address + * + * Returned Value: + * Register value + * + ****************************************************************************/ + +uint32_t IRAM_ATTR esp_dport_access_reg_read(uint32_t reg); + +/**************************************************************************** + * Name: phy_printf + * + * Description: + * Output format string and its arguments + * + * Input Parameters: + * format - format string + * + * Returned Value: + * 0 + * + ****************************************************************************/ + +int phy_printf(const char *format, ...) printf_like(1, 2); + +/**************************************************************************** + * Name: esp_timer_create + * + * Description: + * Create timer with given arguments + * + * Input Parameters: + * create_args - Timer arguments data pointer + * out_handle - Timer handle pointer + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int32_t esp_timer_create(const esp_timer_create_args_t *create_args, + esp_timer_handle_t *out_handle); + +/**************************************************************************** + * Name: esp_timer_start_once + * + * Description: + * Start timer with one shot mode + * + * Input Parameters: + * timer - Timer handle pointer + * timeout_us - Timeout value by micro second + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int32_t esp_timer_start_once(esp_timer_handle_t timer, uint64_t timeout_us); + +/**************************************************************************** + * Name: esp_timer_start_periodic + * + * Description: + * Start timer with periodic mode + * + * Input Parameters: + * timer - Timer handle pointer + * period - Timeout value by micro second + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int32_t esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t period); + +/**************************************************************************** + * Name: esp_timer_stop + * + * Description: + * Stop timer + * + * Input Parameters: + * timer - Timer handle pointer + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int32_t esp_timer_stop(esp_timer_handle_t timer); + +/**************************************************************************** + * Name: esp_timer_delete + * + * Description: + * Delete timer and free resource + * + * Input Parameters: + * timer - Timer handle pointer + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int32_t esp_timer_delete(esp_timer_handle_t timer); + +/**************************************************************************** + * Name: esp_phy_update_country_info + * + * Description: + * Update PHY init data according to country code + * + * Input Parameters: + * country - PHY init data type + * + * Returned Value: + * OK on success; a negated errno on failure + * + ****************************************************************************/ + +int esp_phy_update_country_info(const char *country); + +/**************************************************************************** + * Name: esp_init_semcache + * + * Description: + * Initialize semaphore cache. + * + * Parameters: + * sc - Semaphore cache data pointer + * sem - Semaphore data pointer + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void esp_init_semcache(struct esp_semcache_s *sc, sem_t *sem); + +/**************************************************************************** + * Name: esp_post_semcache + * + * Description: + * Store posting semaphore action into semaphore cache. + * + * Parameters: + * sc - Semaphore cache data pointer + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void esp_post_semcache(struct esp_semcache_s *sc); + +/**************************************************************************** + * Name: esp_init_queuecache + * + * Description: + * Initialize queue cache. + * + * Parameters: + * qc - Queue cache data pointer + * mq_ptr - Queue data pointer + * buffer - Queue cache buffer pointer + * len - Queue cache max length + * size - Queue cache buffer size + * + * Returned Value: + * None. + * + ****************************************************************************/ + +#ifdef CONFIG_ARCH_CHIP_ESP32 +void esp_init_queuecache(struct esp_queuecache_s *qc, + struct file *mq_ptr, + uint8_t *buffer, + size_t len, + size_t size); +#else +void esp_init_queuecache(struct esp_queuecache_s *qc, + struct file *mq_ptr, + uint8_t *buffer, + size_t size); +#endif + +/**************************************************************************** + * Name: esp_send_queuecache + * + * Description: + * Store posting queue action and data into queue cache. + * + * Parameters: + * qc - Queue cache data pointer + * buffer - Data buffer + * size - Buffer size + * + * Returned Value: + * None. + * + ****************************************************************************/ + +#ifdef CONFIG_ARCH_CHIP_ESP32 +void esp_send_queuecache(void *qc, uint8_t *buffer, int size); +#else +void esp_send_queuecache(struct esp_queuecache_s *qc, + uint8_t *buffer, + int size); +#endif + +/**************************************************************************** + * Name: esp_wireless_init + * + * Description: + * Initialize ESP32 wireless common components for both BT and Wi-Fi. + * + * Parameters: + * None + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned on + * failure. + * + ****************************************************************************/ + +int esp_wireless_init(void); + +/**************************************************************************** + * Name: esp_wireless_deinit + * + * Description: + * De-initialize ESP32 wireless common components. + * + * Parameters: + * None + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned on + * failure. + * + ****************************************************************************/ + +int esp_wireless_deinit(void); + +#endif /* __ARCH_XTENSA_SRC_COMMON_ESPRESSIF_ESP_WIRELESS_H */ diff --git a/arch/xtensa/src/common/espressif/esp_wlan.c b/arch/xtensa/src/common/espressif/esp_wlan.c new file mode 100644 index 00000000000..ef109f8e83e --- /dev/null +++ b/arch/xtensa/src/common/espressif/esp_wlan.c @@ -0,0 +1,1786 @@ +/**************************************************************************** + * arch/xtensa/src/common/espressif/esp_wlan.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifdef CONFIG_ESPRESSIF_WIFI + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_NET_PKT) +# include +#endif + +#include "espressif/esp_wlan.h" +#include "espressif/esp_wifi_utils.h" +#include "espressif/esp_wireless.h" + +#ifdef CONFIG_ARCH_CHIP_ESP32 +# include "esp32_wifi_adapter.h" +# include "esp32_systemreset.h" +#elif CONFIG_ARCH_CHIP_ESP32S2 +# include "esp32s2_wifi_adapter.h" +# include "esp32s2_systemreset.h" +#elif CONFIG_ARCH_CHIP_ESP32S3 +# include "esp32s3_wifi_adapter.h" +# include "esp32s3_systemreset.h" +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifdef CONFIG_ARCH_CHIP_ESP32 +# define esp_register_shutdown_handler esp32_register_shutdown_handler +# define esp_unregister_shutdown_handler esp32_unregister_shutdown_handler +#elif CONFIG_ARCH_CHIP_ESP32S2 +# define esp_register_shutdown_handler esp32s2_register_shutdown_handler +# define esp_unregister_shutdown_handler esp32s2_unregister_shutdown_handler +#elif CONFIG_ARCH_CHIP_ESP32S3 +# define esp_register_shutdown_handler esp32s3_register_shutdown_handler +# define esp_unregister_shutdown_handler esp32s3_unregister_shutdown_handler +#endif + +/* TX timeout = 1 minute */ + +#define WLAN_TXTOUT (60 * CLK_TCK) + +/* Low-priority work queue processes RX/TX */ + +#define WLAN_WORK LPWORK + +/* Ethernet frame: + * Resource address : 6 bytes + * Destination address: 6 bytes + * Type : 2 bytes + * Payload : MAX 1500 + * Checksum : Ignore + * + * Total size : 1514 + */ + +#define WLAN_BUF_SIZE (CONFIG_NET_ETH_PKTSIZE) + +/* WLAN packet buffer number */ + +#define WLAN_PKTBUF_NUM (CONFIG_ESPRESSIF_WLAN_PKTBUF_NUM) + +/* Receive threshold which allows the receive function to trigger a scheduler + * to activate the application if possible. + */ + +#ifdef CONFIG_MM_IOB +# define IOBBUF_SIZE (CONFIG_IOB_NBUFFERS * CONFIG_IOB_BUFSIZE) +# if (IOBBUF_SIZE) > (WLAN_BUF_SIZE + 1) +# define WLAN_RX_THRESHOLD (IOBBUF_SIZE - WLAN_BUF_SIZE + 1) +# endif +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* WLAN packet buffer */ + +struct wlan_pktbuf +{ + sq_entry_t entry; /* Queue entry */ + + /* Packet data buffer */ + + uint8_t buffer[WLAN_BUF_SIZE]; + uint16_t len; /* Packet data length */ +}; + +/* WLAN operations */ + +struct wlan_ops +{ + int (*start)(void); + int (*send)(void *pdata, size_t n); + int (*essid)(struct iwreq *iwr, bool set); + int (*bssid)(struct iwreq *iwr, bool set); + int (*passwd)(struct iwreq *iwr, bool set); + int (*mode)(struct iwreq *iwr, bool set); + int (*auth)(struct iwreq *iwr, bool set); + int (*freq)(struct iwreq *iwr, bool set); + int (*bitrate)(struct iwreq *iwr, bool set); + int (*txpower)(struct iwreq *iwr, bool set); + int (*channel)(struct iwreq *iwr, bool set); + int (*country)(struct iwreq *iwr, bool set); + int (*rssi)(struct iwreq *iwr, bool set); + int (*connect)(void); + int (*disconnect)(void); + int (*event)(pid_t pid, struct sigevent *event); + int (*stop)(void); +}; + +/* The wlan_priv_s encapsulates all state information for a single + * hardware interface + */ + +struct wlan_priv_s +{ + int ref; /* Reference count */ + + bool ifup; /* true:ifup false:ifdown */ + + struct wdog_s txtimeout; /* TX timeout timer */ + + struct work_s rxwork; /* Send packet work */ + struct work_s txwork; /* Receive packet work */ + struct work_s pollwork; /* Poll work */ + struct work_s toutwork; /* Send packet timeout work */ + + const struct wlan_ops *ops; /* WLAN operations */ + + /* This holds the information visible to the NuttX network */ + + struct net_driver_s dev; + + /* Packet buffer cache */ + + struct wlan_pktbuf pktbuf[WLAN_PKTBUF_NUM]; + + /* RX packet queue */ + + sq_queue_t rxb; + + /* TX ready packet queue */ + + sq_queue_t txb; + + /* Free packet buffer queue */ + + sq_queue_t freeb; + + /* Device specific lock */ + + spinlock_t lock; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Reference count of register Wi-Fi handler */ + +static uint8_t g_callback_register_ref; + +static struct wlan_priv_s g_wlan_priv[ESPRESSIF_WLAN_DEVS]; + +#ifdef ESPRESSIF_WLAN_HAS_STA +static const struct wlan_ops g_sta_ops = +{ + .start = esp_wifi_sta_start, + .send = esp_wifi_sta_send_data, + .essid = esp_wifi_sta_essid, + .bssid = esp_wifi_sta_bssid, + .passwd = esp_wifi_sta_password, + .mode = esp_wifi_sta_mode, + .auth = esp_wifi_sta_auth, + .freq = esp_wifi_sta_freq, + .bitrate = esp_wifi_sta_bitrate, + .txpower = esp_wifi_sta_txpower, + .channel = esp_wifi_sta_channel, + .country = esp_wifi_sta_country, + .rssi = esp_wifi_sta_rssi, + .connect = esp_wifi_sta_connect, + .disconnect = esp_wifi_sta_disconnect, + .event = esp_wifi_notify_subscribe, + .stop = esp_wifi_sta_stop +}; +#endif /* ESPRESSIF_WLAN_HAS_STA */ + +#ifdef ESPRESSIF_WLAN_HAS_SOFTAP +static const struct wlan_ops g_softap_ops = +{ + .start = esp_wifi_softap_start, + .send = esp_wifi_softap_send_data, + .essid = esp_wifi_softap_essid, + .bssid = esp_wifi_softap_bssid, + .passwd = esp_wifi_softap_password, + .mode = esp_wifi_softap_mode, + .auth = esp_wifi_softap_auth, + .freq = esp_wifi_softap_freq, + .bitrate = esp_wifi_softap_bitrate, + .txpower = esp_wifi_softap_txpower, + .channel = esp_wifi_softap_channel, + .country = esp_wifi_softap_country, + .rssi = esp_wifi_softap_rssi, + .connect = esp_wifi_softap_connect, + .disconnect = esp_wifi_softap_disconnect, + .event = esp_wifi_notify_subscribe, + .stop = esp_wifi_softap_stop +}; +#endif /* ESPRESSIF_WLAN_HAS_SOFTAP */ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Common TX/RX logic */ + +static struct wlan_pktbuf *wlan_recvframe(struct wlan_priv_s *priv); +static struct wlan_pktbuf *wlan_txframe(struct wlan_priv_s *priv); +static void wlan_transmit(struct wlan_priv_s *priv); +static void wlan_rxpoll(void *arg); +static int wlan_txpoll(struct net_driver_s *dev); +static void wlan_dopoll(struct wlan_priv_s *priv); + +/* Watchdog timer expirations */ + +static void wlan_txtimeout_work(void *arg); +static void wlan_txtimeout_expiry(wdparm_t arg); + +/* NuttX callback functions */ + +static int wlan_ifup(struct net_driver_s *dev); +static int wlan_ifdown(struct net_driver_s *dev); + +static void wlan_txavail_work(void *arg); +static int wlan_txavail(struct net_driver_s *dev); + +#if defined(CONFIG_NET_MCASTGROUP) || defined(CONFIG_NET_ICMPv6) +static int wlan_addmac(struct net_driver_s *dev, const uint8_t *mac); +#endif + +#ifdef CONFIG_NET_MCASTGROUP +static int wlan_rmmac(struct net_driver_s *dev, const uint8_t *mac); +#endif + +#ifdef CONFIG_NETDEV_IOCTL +static int wlan_ioctl(struct net_driver_s *dev, int cmd, + unsigned long arg); +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/* Note: + * All TX done/RX done/Error trigger functions are not called from + * interrupts, this is much different from ethernet driver, including: + * * wlan_rx_done + * * wlan_tx_done + * + * These functions are called in a Wi-Fi private thread. So we just use + * mutex/semaphore instead of disable interrupt, if necessary. + */ + +/**************************************************************************** + * Function: wlan_init_buffer + * + * Description: + * Initialize the free buffer list + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + ****************************************************************************/ + +static inline void wlan_init_buffer(struct wlan_priv_s *priv) +{ + irqstate_t flags; + + int i; + flags = spin_lock_irqsave(&priv->lock); + + priv->dev.d_buf = NULL; + priv->dev.d_len = 0; + + sq_init(&priv->freeb); + sq_init(&priv->rxb); + sq_init(&priv->txb); + + for (i = 0; i < WLAN_PKTBUF_NUM; i++) + { + sq_addlast(&priv->pktbuf[i].entry, &priv->freeb); + } + + spin_unlock_irqrestore(&priv->lock, flags); +} + +/**************************************************************************** + * Function: wlan_alloc_buffer + * + * Description: + * Allocate one buffer from the free buffer queue + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * Pointer to the allocated buffer on success; NULL on failure + * + ****************************************************************************/ + +static inline struct wlan_pktbuf *wlan_alloc_buffer(struct wlan_priv_s *priv) +{ + struct wlan_pktbuf *pktbuf = NULL; + + sq_entry_t *entry; + irqstate_t flags = spin_lock_irqsave(&priv->lock); + + entry = sq_remfirst(&priv->freeb); + if (entry) + { + pktbuf = container_of(entry, struct wlan_pktbuf, entry); + } + + spin_unlock_irqrestore(&priv->lock, flags); + + return pktbuf; +} + +/**************************************************************************** + * Function: wlan_free_buffer + * + * Description: + * Insert a free Rx buffer into the free queue + * + * Input Parameters: + * priv - Reference to the driver state structure + * buffer - A pointer to the packet buffer to be freed + * + * Returned Value: + * None + * + ****************************************************************************/ + +static inline void wlan_free_buffer(struct wlan_priv_s *priv, + uint8_t *buffer) +{ + struct wlan_pktbuf *pktbuf; + + irqstate_t flags = spin_lock_irqsave(&priv->lock); + + pktbuf = container_of(buffer, struct wlan_pktbuf, buffer); + sq_addlast(&pktbuf->entry, &priv->freeb); + + spin_unlock_irqrestore(&priv->lock, flags); +} + +/**************************************************************************** + * Function: wlan_cache_txpkt_tail + * + * Description: + * Cache packet from dev->d_buf into tail of TX ready queue. + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + ****************************************************************************/ + +static inline void wlan_cache_txpkt_tail(struct wlan_priv_s *priv) +{ + struct wlan_pktbuf *pktbuf; + irqstate_t flags; + struct net_driver_s *dev = &priv->dev; + + pktbuf = container_of(dev->d_buf, struct wlan_pktbuf, buffer); + pktbuf->len = dev->d_len; + + flags = spin_lock_irqsave(&priv->lock); + sq_addlast(&pktbuf->entry, &priv->txb); + spin_unlock_irqrestore(&priv->lock, flags); + + dev->d_buf = NULL; + dev->d_len = 0; +} + +/**************************************************************************** + * Function: wlan_add_txpkt_head + * + * Description: + * Add packet into head of TX ready queue. + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + ****************************************************************************/ + +static inline void wlan_add_txpkt_head(struct wlan_priv_s *priv, + struct wlan_pktbuf *pktbuf) +{ + irqstate_t flags; + + flags = spin_lock_irqsave(&priv->lock); + sq_addfirst(&pktbuf->entry, &priv->txb); + spin_unlock_irqrestore(&priv->lock, flags); +} + +/**************************************************************************** + * Function: wlan_recvframe + * + * Description: + * Try to receive RX packet from RX done packet queue. + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * RX packet if success or NULl if no packet in queue. + * + ****************************************************************************/ + +static struct wlan_pktbuf *wlan_recvframe(struct wlan_priv_s *priv) +{ + irqstate_t flags; + sq_entry_t *entry; + struct wlan_pktbuf *pktbuf = NULL; + + flags = spin_lock_irqsave(&priv->lock); + + entry = sq_remfirst(&priv->rxb); + if (entry) + { + pktbuf = container_of(entry, struct wlan_pktbuf, entry); + } + + spin_unlock_irqrestore(&priv->lock, flags); + + return pktbuf; +} + +/**************************************************************************** + * Function: wlan_txframe + * + * Description: + * Try to receive TX buffer from TX ready buffer queue. + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * TX packets buffer if success or NULL if no packet in queue. + * + ****************************************************************************/ + +static struct wlan_pktbuf *wlan_txframe(struct wlan_priv_s *priv) +{ + irqstate_t flags; + sq_entry_t *entry; + struct wlan_pktbuf *pktbuf = NULL; + + flags = spin_lock_irqsave(&priv->lock); + + entry = sq_remfirst(&priv->txb); + if (entry) + { + pktbuf = container_of(entry, struct wlan_pktbuf, entry); + } + + spin_unlock_irqrestore(&priv->lock, flags); + + return pktbuf; +} + +/**************************************************************************** + * Name: wlan_transmit + * + * Description: + * Try to send all TX packets in TX ready queue to Wi-Fi driver. If this + * sending fails, then breaks loop and returns. + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void wlan_transmit(struct wlan_priv_s *priv) +{ + struct wlan_pktbuf *pktbuf; + int ret; + + while ((pktbuf = wlan_txframe(priv))) + { + ret = priv->ops->send(pktbuf->buffer, pktbuf->len); + if (ret == -ENOMEM) + { + wlan_add_txpkt_head(priv, pktbuf); + wd_start(&priv->txtimeout, WLAN_TXTOUT, + wlan_txtimeout_expiry, (uint32_t)priv); + break; + } + else + { + if (ret < 0) + { + nwarn("WARN: Failed to send pkt, ret: %d\n", ret); + } + + wlan_free_buffer(priv, pktbuf->buffer); + } + } +} + +/**************************************************************************** + * Name: wlan_tx_done + * + * Description: + * Wi-Fi TX done callback function. If this is called, it means sending + * next packet. + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void wlan_tx_done(struct wlan_priv_s *priv) +{ + wd_cancel(&priv->txtimeout); + + wlan_txavail(&priv->dev); +} + +/**************************************************************************** + * Function: wlan_rx_done + * + * Description: + * Wi-Fi RX done callback function. If this is called, it means receiving + * packet. + * + * Input Parameters: + * priv - Reference to the driver state structure + * buffer - Wi-Fi received packet buffer + * len - Length of received packet + * eb - Wi-Fi receive callback input eb pointer + * + * Returned Value: + * 0 on success or a negated errno on failure + * + ****************************************************************************/ + +static int wlan_rx_done(struct wlan_priv_s *priv, void *buffer, + uint16_t len, void *eb) +{ + struct wlan_pktbuf *pktbuf; + irqstate_t flags; + int ret = 0; + + if (!priv->ifup) + { + goto out; + } + + if (len > WLAN_BUF_SIZE) + { + nwarn("ERROR: Wlan receive %d larger than %d\n", + len, WLAN_BUF_SIZE); + ret = -EINVAL; + goto out; + } + + pktbuf = wlan_alloc_buffer(priv); + if (!pktbuf) + { + ret = -ENOBUFS; + goto out; + } + + memcpy(pktbuf->buffer, buffer, len); + pktbuf->len = len; + + if (eb) + { + esp_wifi_free_eb(eb); + } + + flags = spin_lock_irqsave(&priv->lock); + sq_addlast(&pktbuf->entry, &priv->rxb); + spin_unlock_irqrestore(&priv->lock, flags); + + if (work_available(&priv->rxwork)) + { + work_queue(WLAN_WORK, &priv->rxwork, wlan_rxpoll, priv, 0); + } + + return 0; + +out: + if (eb) + { + esp_wifi_free_eb(eb); + } + + return ret; +} + +/**************************************************************************** + * Function: wlan_rxpoll + * + * Description: + * Try to receive packets from RX done queue and pass packets into IP + * stack and send packets which is from IP stack if necessary. + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void wlan_rxpoll(void *arg) +{ + struct wlan_pktbuf *pktbuf; + struct eth_hdr_s *eth_hdr; + struct wlan_priv_s *priv = (struct wlan_priv_s *)arg; + struct net_driver_s *dev = &priv->dev; +#ifdef WLAN_RX_THRESHOLD + uint32_t rbytes = 0; +#endif + + /* Try to send all cached TX packets for TX ack and so on */ + + wlan_transmit(priv); + + /* Loop while while wlan_recvframe() successfully retrieves valid + * Ethernet frames. + */ + + net_lock(); + + while ((pktbuf = wlan_recvframe(priv)) != NULL) + { + dev->d_buf = pktbuf->buffer; + dev->d_len = pktbuf->len; + +#ifdef WLAN_RX_THRESHOLD + rbytes += pktbuf->len; +#endif + +#ifdef CONFIG_NET_PKT + + /* When packet sockets are enabled, + * feed the frame into the packet tap. + */ + + pkt_input(&priv->dev); +#endif + + /* Check if the packet is a valid size for the network + * buffer configuration (this should not happen) + */ + + if (dev->d_len > WLAN_BUF_SIZE) + { + nwarn("WARNING: DROPPED Too big: %d\n", dev->d_len); + + /* Free dropped packet buffer */ + + if (dev->d_buf) + { + wlan_free_buffer(priv, dev->d_buf); + dev->d_buf = NULL; + dev->d_len = 0; + } + + continue; + } + + eth_hdr = (struct eth_hdr_s *)dev->d_buf; + + /* We only accept IP packets of the configured type and ARP packets */ + +#ifdef CONFIG_NET_IPv4 + if (eth_hdr->type == HTONS(ETHTYPE_IP)) + { + ninfo("IPv4 frame\n"); + + /* Receive an IPv4 packet from the network device */ + + ipv4_input(&priv->dev); + + /* If the above function invocation resulted in data + * that should be sent out on the network, + * the field d_len will set to a value > 0. + */ + + if (priv->dev.d_len > 0) + { + /* And send the packet */ + + wlan_cache_txpkt_tail(priv); + } + } + else +#endif +#ifdef CONFIG_NET_IPv6 + if (eth_hdr->type == HTONS(ETHTYPE_IP6)) + { + ninfo("IPv6 frame\n"); + + /* Give the IPv6 packet to the network layer */ + + ipv6_input(&priv->dev); + + /* If the above function invocation resulted in data + * that should be sent out on the network, the field + * d_len will set to a value > 0. + */ + + if (priv->dev.d_len > 0) + { + /* And send the packet */ + + wlan_cache_txpkt_tail(priv); + } + } + else +#endif +#ifdef CONFIG_NET_ARP + if (eth_hdr->type == HTONS(ETHTYPE_ARP)) + { + ninfo("ARP frame\n"); + + /* Handle ARP packet */ + + arp_input(&priv->dev); + + /* If the above function invocation resulted in data + * that should be sent out on the network, the field + * d_len will set to a value > 0. + */ + + if (priv->dev.d_len > 0) + { + wlan_cache_txpkt_tail(priv); + } + } + else +#endif + { + ninfo("INFO: Dropped, Unknown type: %04x\n", eth_hdr->type); + } + + /* We are finished with the RX buffer. NOTE: If the buffer is + * re-used for transmission, the dev->d_buf field will have been + * nullified. + */ + + if (dev->d_buf) + { + /* Free the receive packet buffer */ + + wlan_free_buffer(priv, dev->d_buf); + dev->d_buf = NULL; + dev->d_len = 0; + } + +#ifdef WLAN_RX_THRESHOLD + /* If received total bytes is larger than receive threshold, + * then do "unlock" to try to active applicantion to receive + * data from low-level buffer of IP stack. + */ + + if (rbytes >= WLAN_RX_THRESHOLD) + { + net_unlock(); + rbytes = 0; + net_lock(); + } +#endif + } + + /* Try to send all cached TX packets */ + + wlan_transmit(priv); + + net_unlock(); +} + +/**************************************************************************** + * Name: wlan_txpoll + * + * Description: + * The transmitter is available, check if the network has any outgoing + * packets ready to send. This is a callback from devif_poll(). + * devif_poll() may be called: + * + * 1. When the preceding TX packets send times out and the interface is + * reset + * 2. During normal TX polling + * + * Input Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * OK on success; a negated errno on failure + * + ****************************************************************************/ + +static int wlan_txpoll(struct net_driver_s *dev) +{ + struct wlan_pktbuf *pktbuf; + struct wlan_priv_s *priv = (struct wlan_priv_s *)dev->d_private; + + DEBUGASSERT(dev->d_buf != NULL); + + wlan_cache_txpkt_tail(priv); + + pktbuf = wlan_alloc_buffer(priv); + if (!pktbuf) + { + return -ENOMEM; + } + + dev->d_buf = pktbuf->buffer; + dev->d_len = WLAN_BUF_SIZE; + + /* If zero is returned, the polling will continue until + * all connections have been examined. + */ + + return OK; +} + +/**************************************************************************** + * Function: wlan_dopoll + * + * Description: + * The function is called in order to perform an out-of-sequence TX poll. + * This is done: + * + * 1. When new TX data is available (wlan_txavail) + * 2. After a TX timeout to restart the sending process + * (wlan_txtimeout_expiry). + * + * Input Parameters: + * priv - Reference to the driver state structure + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void wlan_dopoll(struct wlan_priv_s *priv) +{ + struct net_driver_s *dev = &priv->dev; + struct wlan_pktbuf *pktbuf; + uint8_t *txbuf; + int ret; + + pktbuf = wlan_alloc_buffer(priv); + if (!pktbuf) + { + return ; + } + + dev->d_buf = pktbuf->buffer; + dev->d_len = WLAN_BUF_SIZE; + + /* Try to let TCP/IP to send all packets to netcard driver */ + + do + { + txbuf = dev->d_buf; + ret = devif_poll(dev, wlan_txpoll); + } + while ((ret == 0) && + (dev->d_buf != txbuf)); + + if (dev->d_buf) + { + wlan_free_buffer(priv, dev->d_buf); + + dev->d_buf = NULL; + dev->d_len = 0; + } + + /* Try to send all cached TX packets */ + + wlan_transmit(priv); +} + +/**************************************************************************** + * Function: wlan_txtimeout_work + * + * Description: + * Perform TX timeout related work from the worker thread + * + * Input Parameters: + * arg - The argument passed when work_queue() as called. + * + * Returned Value: + * OK on success + * + ****************************************************************************/ + +static void wlan_txtimeout_work(void *arg) +{ + struct wlan_priv_s *priv = (struct wlan_priv_s *)arg; + + /* Try to send all cached TX packets */ + + wlan_transmit(priv); + + net_lock(); + + wlan_ifdown(&priv->dev); + wlan_ifup(&priv->dev); + + /* Then poll for new XMIT data */ + + wlan_dopoll(priv); + + net_unlock(); +} + +/**************************************************************************** + * Function: wlan_txtimeout_expiry + * + * Description: + * Our TX watchdog timed out. Called from the timer callback handler. + * The last TX never completed. Reset the hardware and start again. + * + * Input Parameters: + * argc - The number of available arguments + * arg - The first argument + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void wlan_txtimeout_expiry(wdparm_t arg) +{ + struct wlan_priv_s *priv = (struct wlan_priv_s *)arg; + + /* Schedule to perform the TX timeout processing on the worker thread. */ + + if (work_available(&priv->toutwork)) + { + work_queue(WLAN_WORK, &priv->toutwork, wlan_txtimeout_work, priv, 0); + } +} + +/**************************************************************************** + * Name: wlan_txavail_work + * + * Description: + * Perform an out-of-cycle poll on the worker thread. + * + * Input Parameters: + * arg - Reference to the NuttX driver state structure (cast to void*) + * + * Returned Value: + * None + * + * Assumptions: + * Called on the higher priority worker thread. + * + ****************************************************************************/ + +static void wlan_txavail_work(void *arg) +{ + struct wlan_priv_s *priv = (struct wlan_priv_s *)arg; + + /* Try to send all cached TX packets even if net is down */ + + wlan_transmit(priv); + + /* Lock the network and serialize driver operations if necessary. + * NOTE: Serialization is only required in the case where the driver work + * is performed on an LP worker thread and where more than one LP worker + * thread has been configured. + */ + + net_lock(); + + /* Ignore the notification if the interface is not yet up */ + + if (priv->ifup) + { + /* Poll the network for new XMIT data */ + + wlan_dopoll(priv); + } + + net_unlock(); +} + +/**************************************************************************** + * Name: wlan_ifup + * + * Description: + * NuttX Callback: Bring up the Ethernet interface when an IP address is + * provided + * + * Input Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + ****************************************************************************/ + +static int wlan_ifup(struct net_driver_s *dev) +{ + int ret; + struct wlan_priv_s *priv = (struct wlan_priv_s *)dev->d_private; + +#ifdef CONFIG_NET_IPv4 + ninfo("Bringing up: %u.%u.%u.%u\n", + ip4_addr1(dev->d_ipaddr), ip4_addr2(dev->d_ipaddr), + ip4_addr3(dev->d_ipaddr), ip4_addr4(dev->d_ipaddr)); +#endif +#ifdef CONFIG_NET_IPv6 + ninfo("Bringing up: %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", + dev->d_ipv6addr[0], dev->d_ipv6addr[1], dev->d_ipv6addr[2], + dev->d_ipv6addr[3], dev->d_ipv6addr[4], dev->d_ipv6addr[5], + dev->d_ipv6addr[6], dev->d_ipv6addr[7]); +#endif + + net_lock(); + + if (priv->ifup) + { + net_unlock(); + return OK; + } + + wlan_init_buffer(priv); + ret = priv->ops->start(); + if (ret < 0) + { + net_unlock(); + nerr("ERROR: Failed to start Wi-Fi ret=%d\n", ret); + return ret; + } + + priv->ifup = true; + if (g_callback_register_ref == 0) + { + ret = esp_register_shutdown_handler(esp_wifi_stop_callback); + if (ret < 0) + { + nwarn("WARN: Failed to register handler ret=%d\n", ret); + } + } + + ++g_callback_register_ref; + net_unlock(); + + return OK; +} + +/**************************************************************************** + * Name: wlan_ifdown + * + * Description: + * NuttX Callback: Stop the interface. + * + * Input Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + ****************************************************************************/ + +static int wlan_ifdown(struct net_driver_s *dev) +{ + int ret; + struct wlan_priv_s *priv = (struct wlan_priv_s *)dev->d_private; + + net_lock(); + + if (!priv->ifup) + { + net_unlock(); + return OK; + } + + /* Cancel the TX poll timer and TX timeout timers */ + + wd_cancel(&priv->txtimeout); + + /* Mark the device "down" */ + + priv->ifup = false; + + ret = priv->ops->stop(); + if (ret < 0) + { + nerr("ERROR: Failed to stop Wi-Fi ret=%d\n", ret); + } + + --g_callback_register_ref; + if (g_callback_register_ref == 0) + { + ret = esp_unregister_shutdown_handler(esp_wifi_stop_callback); + if (ret < 0) + { + nwarn("WARN: Failed to unregister handler ret=%d\n", ret); + } + } + + net_unlock(); + + return OK; +} + +/**************************************************************************** + * Name: wlan_txavail + * + * Description: + * Driver callback invoked when new TX data is available. This is a + * stimulus perform an out-of-cycle poll and, thereby, reduce the TX + * latency. + * + * Input Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Called in normal user mode + * + ****************************************************************************/ + +static int wlan_txavail(struct net_driver_s *dev) +{ + struct wlan_priv_s *priv = (struct wlan_priv_s *)dev->d_private; + + if (work_available(&priv->txwork)) + { + /* Schedule to serialize the poll on the worker thread. */ + + work_queue(WLAN_WORK, &priv->txwork, wlan_txavail_work, priv, 0); + } + + return OK; +} + +/**************************************************************************** + * Name: wlan_addmac + * + * Description: + * NuttX Callback: Add the specified MAC address to the hardware multicast + * address filtering + * + * Input Parameters: + * dev - Reference to the NuttX driver state structure + * mac - The MAC address to be added + * + * Returned Value: + * None + * + ****************************************************************************/ + +#if defined(CONFIG_NET_MCASTGROUP) || defined(CONFIG_NET_ICMPv6) +static int wlan_addmac(struct net_driver_s *dev, const uint8_t *mac) +{ + struct wlan_priv_s *priv = (struct wlan_priv_s *)dev->d_private; + + /* Add the MAC address to the hardware multicast routing table */ + + return OK; +} +#endif + +/**************************************************************************** + * Name: wlan_rmmac + * + * Description: + * NuttX Callback: Remove the specified MAC address from the + * hardware multicast address filtering + * + * Input Parameters: + * dev - Reference to the NuttX driver state structure + * mac - The MAC address to be removed + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_NET_MCASTGROUP +static int wlan_rmmac(struct net_driver_s *dev, const uint8_t *mac) +{ + struct wlan_priv_s *priv = (struct wlan_priv_s *)dev->d_private; + + /* Add the MAC address to the hardware multicast routing table */ + + return OK; +} +#endif + +/**************************************************************************** + * Name: wlan_ioctl + * + * Description: + * Handle network IOCTL commands directed to this device. + * + * Input Parameters: + * dev - Reference to the NuttX driver state structure + * cmd - The IOCTL command + * arg - The argument for the IOCTL command + * + * Returned Value: + * OK on success; Negated errno on failure. + * + ****************************************************************************/ + +#ifdef CONFIG_NETDEV_IOCTL +static int wlan_ioctl(struct net_driver_s *dev, + int cmd, + unsigned long arg) +{ + int ret; + struct iwreq *iwr = (struct iwreq *)arg; + struct wlan_priv_s *priv = (struct wlan_priv_s *)dev->d_private; + const struct wlan_ops *ops = priv->ops; + + /* Decode and dispatch the driver-specific IOCTL command */ + + switch (cmd) + { +#ifdef CONFIG_NETDEV_PHY_IOCTL +#ifdef CONFIG_ARCH_PHY_INTERRUPT + case SIOCMIINOTIFY: /* Set up for PHY event notifications */ + { + struct mii_ioctl_notify_s *req = (struct mii_ioctl_notify_s *)arg; + ret = ops->event(req->pid, &req->event); + if (ret < 0) + { + nerr("ERROR: Failed to subscribe event\n"); + } + } + break; +#endif +#endif + + case SIOCSIWENCODEEXT: + ret = ops->passwd(iwr, true); + + break; + + case SIOCGIWENCODEEXT: + ret = ops->passwd(iwr, false); + break; + + case SIOCSIWESSID: + if ((iwr->u.essid.flags == IW_ESSID_ON) || + (iwr->u.essid.flags == IW_ESSID_DELAY_ON)) + { + ret = ops->essid(iwr, true); + if (ret < 0) + { + break; + } + + if (iwr->u.essid.flags == IW_ESSID_ON) + { + ret = ops->connect(); + if (ret < 0) + { + nerr("ERROR: Failed to connect\n"); + break; + } + } + } + else + { + ret = ops->disconnect(); + if (ret < 0) + { + nerr("ERROR: Failed to disconnect\n"); + break; + } + } + + break; + + case SIOCGIWESSID: /* Get ESSID */ + ret = ops->essid(iwr, false); + break; + + case SIOCSIWAP: /* Set access point MAC addresses */ + if (iwr->u.ap_addr.sa_data[0] != 0 && + iwr->u.ap_addr.sa_data[1] != 0 && + iwr->u.ap_addr.sa_data[2] != 0) + { + ret = ops->bssid(iwr, true); + if (ret < 0) + { + nerr("ERROR: Failed to set BSSID\n"); + break; + } + + ret = ops->connect(); + if (ret < 0) + { + nerr("ERROR: Failed to connect\n"); + break; + } + } + else + { + ret = ops->disconnect(); + if (ret < 0) + { + nerr("ERROR: Failed to disconnect\n"); + break; + } + } + + break; + + case SIOCGIWAP: /* Get access point MAC addresses */ + ret = ops->bssid(iwr, false); + break; + + case SIOCSIWSCAN: + ret = esp_wifi_start_scan(iwr); + break; + + case SIOCGIWSCAN: + ret = esp_wifi_get_scan_results(iwr); + break; + + case SIOCSIWCOUNTRY: /* Set country code */ + ret = ops->country(iwr, true); + break; + + case SIOCGIWSENS: /* Get sensitivity (dBm) */ + ret = ops->rssi(iwr, false); + break; + + case SIOCSIWMODE: /* Set operation mode */ + ret = ops->mode(iwr, true); + break; + + case SIOCGIWMODE: /* Get operation mode */ + ret = ops->mode(iwr, false); + break; + + case SIOCSIWAUTH: /* Set authentication mode params */ + ret = ops->auth(iwr, true); + break; + + case SIOCGIWAUTH: /* Get authentication mode params */ + ret = ops->auth(iwr, false); + break; + + case SIOCSIWFREQ: /* Set channel/frequency (MHz) */ + ret = ops->freq(iwr, true); + break; + + case SIOCGIWFREQ: /* Get channel/frequency (MHz) */ + ret = ops->freq(iwr, false); + break; + + case SIOCSIWRATE: /* Set default bit rate (Mbps) */ + wlwarn("WARNING: SIOCSIWRATE not implemented\n"); + ret = -ENOSYS; + break; + + case SIOCGIWRATE: /* Get default bit rate (Mbps) */ + ret = ops->bitrate(iwr, false); + break; + + case SIOCSIWTXPOW: /* Set transmit power (dBm) */ + ret = ops->txpower(iwr, true); + break; + + case SIOCGIWTXPOW: /* Get transmit power (dBm) */ + ret = ops->txpower(iwr, false); + break; + + case SIOCGIWRANGE: /* Get range of parameters */ + ret = ops->channel(iwr, false); + break; + + default: + nerr("ERROR: Unrecognized IOCTL command: %d\n", cmd); + ret = -ENOTTY; /* Special return value for this case */ + break; + } + + return ret; +} +#endif /* CONFIG_NETDEV_IOCTL */ + +/**************************************************************************** + * Name: esp_net_initialize + * + * Description: + * Initialize the ESP32-S2 driver + * + * Input Parameters: + * devno - The device number + * mac_addr - MAC address + * + * Returned Value: + * OK on success; Negated errno on failure. + * + ****************************************************************************/ + +static int esp_net_initialize(int devno, uint8_t *mac_addr, + const struct wlan_ops *ops) +{ + int ret; + struct wlan_priv_s *priv; + struct net_driver_s *netdev; + + priv = &g_wlan_priv[devno]; + if (priv->ref) + { + priv->ref++; + return OK; + } + + netdev = &priv->dev; + + /* Initialize the driver structure */ + + memset(priv, 0, sizeof(struct wlan_priv_s)); + + netdev->d_ifup = wlan_ifup; /* I/F down callback */ + netdev->d_ifdown = wlan_ifdown; /* I/F up (new IP address) callback */ + netdev->d_txavail = wlan_txavail; /* New TX data callback */ +#ifdef CONFIG_NET_MCASTGROUP + netdev->d_addmac = wlan_addmac; /* Add multicast MAC address */ + netdev->d_rmmac = wlan_rmmac; /* Remove multicast MAC address */ +#endif +#ifdef CONFIG_NETDEV_IOCTL + netdev->d_ioctl = wlan_ioctl; /* Handle network IOCTL commands */ +#endif + + /* Used to recover private state from dev */ + + netdev->d_private = (void *)priv; + + memcpy(netdev->d_mac.ether.ether_addr_octet, mac_addr, MAC_LEN); + + ret = netdev_register(netdev, NET_LL_IEEE80211); + if (ret < 0) + { + nerr("ERROR: Initialization of IEEE 802.11 block failed: %d\n", ret); + return ret; + } + + priv->ops = ops; + + priv->ref++; + + ninfo("INFO: Initialize Wi-Fi adapter No.%d success\n", devno); + + return OK; +} + +/**************************************************************************** + * Function: wlan_sta_rx_done + * + * Description: + * Wi-Fi station RX done callback function. If this is called, it means + * station receiveing packet. + * + * Input Parameters: + * buffer - Wi-Fi received packet buffer + * len - Length of received packet + * eb - Wi-Fi receive callback input eb pointer + * + * Returned Value: + * 0 on success or a negated errno on failure + * + ****************************************************************************/ + +#ifdef ESPRESSIF_WLAN_HAS_STA +static int wlan_sta_rx_done(void *buffer, uint16_t len, void *eb) +{ + struct wlan_priv_s *priv = &g_wlan_priv[ESPRESSIF_WLAN_STA_DEVNO]; + + return wlan_rx_done(priv, buffer, len, eb); +} + +/**************************************************************************** + * Name: wlan_sta_tx_done + * + * Description: + * Wi-Fi station TX done callback function. If this is called, it means + * station sending next packet. + * + * Input Parameters: + * data - Pointer to the data transmitted. + * len - Length of the data transmitted. + * status - True if data was transmitted successfully or false if failed. + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void wlan_sta_tx_done(uint8_t *data, uint16_t *len, bool status) +{ + struct wlan_priv_s *priv = &g_wlan_priv[ESPRESSIF_WLAN_STA_DEVNO]; + + wlan_tx_done(priv); +} +#endif /* ESPRESSIF_WLAN_HAS_STA */ + +/**************************************************************************** + * Function: wlan_softap_rx_done + * + * Description: + * Wi-Fi softAP RX done callback function. If this is called, it means + * softAP receiveing packet. + * + * Input Parameters: + * buffer - Wi-Fi received packet buffer + * len - Length of received packet + * eb - Wi-Fi receive callback input eb pointer + * + * Returned Value: + * 0 on success or a negated errno on failure + * + ****************************************************************************/ + +#ifdef ESPRESSIF_WLAN_HAS_SOFTAP +static int wlan_softap_rx_done(void *buffer, uint16_t len, void *eb) +{ + struct wlan_priv_s *priv = &g_wlan_priv[ESPRESSIF_WLAN_SOFTAP_DEVNO]; + + return wlan_rx_done(priv, buffer, len, eb); +} + +/**************************************************************************** + * Name: wlan_softap_tx_done + * + * Description: + * Wi-Fi softAP TX done callback function. If this is called, it means + * softAP sending next packet. + * + * Input Parameters: + * ifidx - The interface ID that the TX callback has been triggered from. + * data - Pointer to the data transmitted. + * len - Length of the data transmitted. + * status - True if data was transmitted successfully or false if failed. + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void wlan_softap_tx_done(uint8_t *data, uint16_t *len, bool status) +{ + struct wlan_priv_s *priv = &g_wlan_priv[ESPRESSIF_WLAN_SOFTAP_DEVNO]; + + wlan_tx_done(priv); +} +#endif /* ESPRESSIF_WLAN_HAS_SOFTAP */ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: esp_wlan_sta_set_linkstatus + * + * Description: + * Set Wi-Fi station link status + * + * Parameters: + * linkstatus - true Notifies the networking layer about an available + * carrier, false Notifies the networking layer about an + * disappeared carrier. + * + * Returned Value: + * OK on success; Negated errno on failure. + * + ****************************************************************************/ + +#ifdef ESPRESSIF_WLAN_HAS_STA +int esp_wlan_sta_set_linkstatus(bool linkstatus) +{ + struct wlan_priv_s *priv = &g_wlan_priv[ESPRESSIF_WLAN_STA_DEVNO]; + + if (linkstatus) + { + netdev_carrier_on(&priv->dev); + } + else + { + netdev_carrier_off(&priv->dev); + } + + return OK; +} + +/**************************************************************************** + * Name: esp_wlan_sta_initialize + * + * Description: + * Initialize the ESP32-S2 WLAN station netcard driver + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success; Negated errno on failure. + * + ****************************************************************************/ + +int esp_wlan_sta_initialize(void) +{ + int ret; + uint8_t eth_mac[6]; + + ret = esp_wifi_adapter_init(); + if (ret < 0) + { + nerr("ERROR: Initialize Wi-Fi adapter error: %d\n", ret); + return ret; + } + + ret = esp_wifi_sta_read_mac(eth_mac); + if (ret < 0) + { + nerr("ERROR: Failed to read MAC address\n"); + return ret; + } + + ninfo("Wi-Fi station MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", + eth_mac[0], eth_mac[1], eth_mac[2], + eth_mac[3], eth_mac[4], eth_mac[5]); + + ret = esp_net_initialize(ESPRESSIF_WLAN_STA_DEVNO, + eth_mac, &g_sta_ops); + if (ret < 0) + { + nerr("ERROR: Failed to initialize net\n"); + return ret; + } + + ret = esp_wifi_sta_register_recv_cb(wlan_sta_rx_done); + if (ret < 0) + { + nerr("ERROR: Failed to register RX callback\n"); + return ret; + } + + esp_wifi_sta_register_txdone_cb(wlan_sta_tx_done); + + ninfo("INFO: Initialize Wi-Fi station success net\n"); + + return OK; +} +#endif /* ESPRESSIF_WLAN_HAS_STA */ + +/**************************************************************************** + * Name: esp_wlan_softap_initialize + * + * Description: + * Initialize the ESP32-S2 WLAN softAP netcard driver + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success; Negated errno on failure. + * + ****************************************************************************/ + +#ifdef ESPRESSIF_WLAN_HAS_SOFTAP +int esp_wlan_softap_initialize(void) +{ + int ret; + uint8_t eth_mac[6]; + + ret = esp_wifi_adapter_init(); + if (ret < 0) + { + nerr("ERROR: Initialize Wi-Fi adapter error: %d\n", ret); + return ret; + } + + ret = esp_wifi_softap_read_mac(eth_mac); + if (ret < 0) + { + nerr("ERROR: Failed to read MAC address\n"); + return ret; + } + + ninfo("Wi-Fi softAP MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", + eth_mac[0], eth_mac[1], eth_mac[2], + eth_mac[3], eth_mac[4], eth_mac[5]); + + ret = esp_net_initialize(ESPRESSIF_WLAN_SOFTAP_DEVNO, eth_mac, + &g_softap_ops); + if (ret < 0) + { + nerr("ERROR: Failed to initialize net\n"); + return ret; + } + + ret = esp_wifi_softap_register_recv_cb(wlan_softap_rx_done); + if (ret < 0) + { + nerr("ERROR: Failed to register RX callback\n"); + return ret; + } + + esp_wifi_softap_register_txdone_cb(wlan_softap_tx_done); + + ninfo("INFO: Initialize Wi-Fi softAP net success\n"); + + return OK; +} +#endif /* ESPRESSIF_WLAN_HAS_SOFTAP */ + +#endif /* CONFIG_ESPRESSIF_WIFI */ diff --git a/arch/xtensa/src/common/espressif/esp_wlan.h b/arch/xtensa/src/common/espressif/esp_wlan.h new file mode 100644 index 00000000000..a211f5d18eb --- /dev/null +++ b/arch/xtensa/src/common/espressif/esp_wlan.h @@ -0,0 +1,119 @@ +/**************************************************************************** + * arch/xtensa/src/common/espressif/esp_wlan.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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 __ARCH_XTENSA_SRC_COMMON_ESPRESSIF_ESP_WLAN_H +#define __ARCH_XTENSA_SRC_COMMON_ESPRESSIF_ESP_WLAN_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifdef CONFIG_ARCH_CHIP_ESP32S2 +# include "esp32s2_wifi_adapter.h" +#endif + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +#ifdef CONFIG_ESPRESSIF_WIFI + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +# + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef ESPRESSIF_WLAN_HAS_STA + +/**************************************************************************** + * Name: esp_wlan_sta_set_linkstatus + * + * Description: + * Set Wi-Fi station link status + * + * Parameters: + * linkstatus - true Notifies the networking layer about an available + * carrier, false Notifies the networking layer about an + * disappeared carrier. + * + * Returned Value: + * OK on success; Negated errno on failure. + * + ****************************************************************************/ + +int esp_wlan_sta_set_linkstatus(bool linkstatus); + +/**************************************************************************** + * Name: esp_wlan_sta_initialize + * + * Description: + * Initialize the ESP32|S2|S3 WLAN station netcard driver + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success; Negated errno on failure. + * + ****************************************************************************/ + +int esp_wlan_sta_initialize(void); +#endif /* ESPRESSIF_WLAN_HAS_STA */ + +/**************************************************************************** + * Name: esp_wlan_softap_initialize + * + * Description: + * Initialize the ESP32|S2|S3 WLAN softAP netcard driver + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success; Negated errno on failure. + * + ****************************************************************************/ + +#ifdef ESPRESSIF_WLAN_HAS_SOFTAP +int esp_wlan_softap_initialize(void); +#endif /* ESPRESSIF_WLAN_HAS_SOFTAP */ + +#endif /* CONFIG_ESPRESSIF_WIFI */ +#ifdef __cplusplus +} +#endif +#undef EXTERN + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_XTENSA_SRC_COMMON_ESPRESSIF_ESP_WLAN_H */ diff --git a/arch/xtensa/src/esp32s2/Make.defs b/arch/xtensa/src/esp32s2/Make.defs index 7853246f93b..76c4b571bc5 100644 --- a/arch/xtensa/src/esp32s2/Make.defs +++ b/arch/xtensa/src/esp32s2/Make.defs @@ -131,6 +131,10 @@ ifeq ($(CONFIG_RTC_DRIVER),y) CHIP_CSRCS += esp32s2_rtc_lowerhalf.c endif +ifeq ($(CONFIG_ESPRESSIF_WIFI),y) +CHIP_CSRCS += esp32s2_wifi_adapter.c +endif + ############################################################################# # Espressif HAL for 3rd Party Platforms ############################################################################# @@ -139,7 +143,7 @@ endif ESP_HAL_3RDPARTY_REPO = esp-hal-3rdparty ifndef ESP_HAL_3RDPARTY_VERSION - ESP_HAL_3RDPARTY_VERSION = 3986249ef8f567bf542bc35ab283ef488f9fd8e2 + ESP_HAL_3RDPARTY_VERSION = 7857ae934736b2de2a387d90bd491fde2b3a5377 endif ifndef ESP_HAL_3RDPARTY_URL @@ -169,6 +173,13 @@ include common/espressif/Make.defs include chip/Bootloader.mk context:: chip/$(ESP_HAL_3RDPARTY_REPO) +ifeq ($(CONFIG_ESPRESSIF_WIRELESS),y) + $(Q) echo "Espressif HAL for 3rd Party Platforms: initializing submodules..." + $(Q) git -C chip/$(ESP_HAL_3RDPARTY_REPO) submodule --quiet update --init $(GIT_DEPTH_PARAMETER) components/mbedtls/mbedtls components/esp_phy/lib components/esp_wifi/lib + $(Q) git -C chip/$(ESP_HAL_3RDPARTY_REPO)/components/mbedtls/mbedtls reset --quiet --hard + $(Q) echo "Applying patches..." + $(Q) cd chip/$(ESP_HAL_3RDPARTY_REPO)/components/mbedtls/mbedtls && git apply ../../../nuttx/patches/components/mbedtls/mbedtls/*.patch +endif distclean:: $(call DELDIR,chip/$(ESP_HAL_3RDPARTY_REPO)) diff --git a/arch/xtensa/src/esp32s2/esp32s2_irq.c b/arch/xtensa/src/esp32s2/esp32s2_irq.c index 509b32ef678..a5ac3827877 100644 --- a/arch/xtensa/src/esp32s2/esp32s2_irq.c +++ b/arch/xtensa/src/esp32s2/esp32s2_irq.c @@ -81,6 +81,12 @@ #define ESP32S2_MAX_PRIORITY 5 #define ESP32S2_PRIO_INDEX(p) ((p) - ESP32S2_MIN_PRIORITY) +#ifdef CONFIG_ESPRESSIF_WIFI +# define ESP32S2_WIFI_RESERVE_INT (1 << ESP32S2_CPUINT_MAC) +#else +# define ESP32S2_WIFI_RESERVE_INT 0 +#endif + /**************************************************************************** * Private Data ****************************************************************************/ @@ -99,7 +105,8 @@ static uint32_t g_intenable; * devices. */ -static uint32_t g_cpu_freeints = ESP32S2_CPUINT_PERIPHSET; +static uint32_t g_cpu_freeints = ESP32S2_CPUINT_PERIPHSET & + ~ESP32S2_WIFI_RESERVE_INT; /* Bitsets for each interrupt priority 1-5 */ @@ -287,13 +294,24 @@ void up_irqinitialize(void) /* Hard code special cases. */ g_irqmap[XTENSA_IRQ_TIMER0] = ESP32S2_CPUINT_TIMER0; - g_irqmap[XTENSA_IRQ_SWINT] = ESP32S2_CPUINT_SOFTWARE1; +#ifdef CONFIG_ESPRESSIF_WIFI + g_irqmap[ESP32S2_IRQ_MAC] = ESP32S2_CPUINT_MAC; + g_irqmap[ESP32S2_IRQ_PWR] = ESP32S2_CPUINT_PWR; +#endif /* Initialize CPU interrupts */ esp32s2_cpuint_initialize(); + /* Reserve interrupt for some special drivers */ + +#ifdef CONFIG_ESPRESSIF_WIFI + g_cpu_intmap[ESP32S2_CPUINT_MAC] = CPUINT_ASSIGN(ESP32S2_IRQ_MAC); + g_cpu_intmap[ESP32S2_CPUINT_PWR] = CPUINT_ASSIGN(ESP32S2_IRQ_PWR); + xtensa_enable_cpuint(&g_intenable, 1 << ESP32S2_CPUINT_MAC); +#endif + #ifdef CONFIG_ESP32S2_GPIO_IRQ /* Initialize GPIO interrupt support */ @@ -634,4 +652,3 @@ uint32_t *xtensa_int_decode(uint32_t cpuints, uint32_t *regs) return regs; } - diff --git a/arch/xtensa/src/esp32s2/esp32s2_rng.c b/arch/xtensa/src/esp32s2/esp32s2_rng.c index 5d7d662688b..af659234869 100644 --- a/arch/xtensa/src/esp32s2/esp32s2_rng.c +++ b/arch/xtensa/src/esp32s2/esp32s2_rng.c @@ -45,6 +45,8 @@ #include "hardware/wdev_reg.h" #include "esp32s2_clockconfig.h" +#include "esp_random.h" + #if defined(CONFIG_ESP32S2_RNG) #if defined(CONFIG_DEV_RANDOM) || defined(CONFIG_DEV_URANDOM_ARCH) @@ -83,42 +85,6 @@ static const struct file_operations g_rngops = * Private functions ****************************************************************************/ -/**************************************************************************** - * Name: esp32s2_random - ****************************************************************************/ - -uint32_t IRAM_ATTR esp_random(void) -{ - /* The PRNG which implements WDEV_RANDOM register gets 2 bits - * of extra entropy from a hardware randomness source every APB clock cycle - * (provided Wi-Fi or BT are enabled). To make sure entropy is not drained - * faster than it is added, this function needs to wait for at least 16 APB - * clock cycles after reading previous word. This implementation may - * actually wait a bit longer due to extra time spent in arithmetic and - * branch statements. - * - * As a (probably unnecessary) precaution to avoid returning the - * RNG state as-is, the result is XORed with additional - * WDEV_RND_REG reads while waiting. - */ - - uint32_t cpu_to_apb_freq_ratio = esp_clk_cpu_freq() / esp_clk_apb_freq(); - - static uint32_t last_ccount = 0; - uint32_t ccount; - uint32_t result = 0; - - do - { - ccount = XTHAL_GET_CCOUNT(); - result ^= getreg32(WDEV_RND_REG); - } - while (ccount - last_ccount < cpu_to_apb_freq_ratio * 16); - - last_ccount = ccount; - return result ^ getreg32(WDEV_RND_REG); -} - /**************************************************************************** * Name: esp32s2_rng_read ****************************************************************************/ diff --git a/arch/xtensa/src/esp32s2/esp32s2_start.c b/arch/xtensa/src/esp32s2/esp32s2_start.c index b1d2206d51f..ae0262de7b1 100644 --- a/arch/xtensa/src/esp32s2/esp32s2_start.c +++ b/arch/xtensa/src/esp32s2/esp32s2_start.c @@ -50,12 +50,17 @@ #include "hal/cache_types.h" #include "hal/cache_ll.h" #include "hal/cache_hal.h" +#include "hal/sar_ctrl_ll.h" #include "rom/spi_flash.h" #ifdef CONFIG_ESPRESSIF_SIMPLE_BOOT # include "bootloader_init.h" #endif +#include "bootloader_random.h" +#include "bootloader_soc.h" +#include "esp_clk_internal.h" + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -346,6 +351,17 @@ static void noreturn_function IRAM_ATTR __esp32s2_start(void) } #endif + /* Initialize peripherals parameters */ + + esp_perip_clk_init(); + + /* RNG is enabled during boot and must be disabled otherwise + * Wi-Fi gets unstable. + */ + + bootloader_random_disable(); + bootloader_ana_clock_glitch_reset_config(false); + /* The 2nd stage bootloader enables RTC WDT to check on startup sequence * related issues in application. Hence disable that as we are about to * start the NuttX environment. diff --git a/arch/xtensa/src/esp32s2/esp32s2_systemreset.c b/arch/xtensa/src/esp32s2/esp32s2_systemreset.c index 8d03f9994cc..2f730758f32 100644 --- a/arch/xtensa/src/esp32s2/esp32s2_systemreset.c +++ b/arch/xtensa/src/esp32s2/esp32s2_systemreset.c @@ -37,6 +37,10 @@ * Pre-processor Definitions ****************************************************************************/ +/* Each handler allows setting a callback function which is called in case + * of a system reset, for whatever reason. + */ + #define SHUTDOWN_HANDLERS_NO 4 /**************************************************************************** diff --git a/arch/xtensa/src/esp32s2/esp32s2_systemreset.h b/arch/xtensa/src/esp32s2/esp32s2_systemreset.h index 2e314ed995f..3bdb5e5cfc2 100644 --- a/arch/xtensa/src/esp32s2/esp32s2_systemreset.h +++ b/arch/xtensa/src/esp32s2/esp32s2_systemreset.h @@ -18,8 +18,8 @@ * ****************************************************************************/ -#ifndef __ARCH_XTENSA_SRC_ESP32S3_ESP32S3_SYSTEMRESET_H -#define __ARCH_XTENSA_SRC_ESP32S3_ESP32S3_SYSTEMRESET_H +#ifndef __ARCH_XTENSA_SRC_ESP32S2_ESP32S2_SYSTEMRESET_H +#define __ARCH_XTENSA_SRC_ESP32S2_ESP32S2_SYSTEMRESET_H /**************************************************************************** * Included Files diff --git a/arch/xtensa/src/esp32s2/esp32s2_wifi_adapter.c b/arch/xtensa/src/esp32s2/esp32s2_wifi_adapter.c new file mode 100644 index 00000000000..6852f740267 --- /dev/null +++ b/arch/xtensa/src/esp32s2/esp32s2_wifi_adapter.c @@ -0,0 +1,6495 @@ +/**************************************************************************** + * arch/xtensa/src/esp32s2/esp32s2_wifi_adapter.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "xtensa.h" +#include "esp_attr.h" +#include "hardware/esp32s2_system.h" +#include "hardware/esp32s2_rtccntl.h" +#include "hardware/esp32s2_syscon.h" +#include "hardware/esp32s2_soc.h" +#include "esp32s2_irq.h" +#include "espressif/esp_wireless.h" +#include "esp32s2_wifi_adapter.h" +#include "esp32s2_rt_timer.h" +#include "espressif/esp_wifi_utils.h" +#include "espressif/esp_wlan.h" + +#include "esp_log.h" +#include "esp_mac.h" +#include "esp_private/phy.h" +#include "esp_private/wifi.h" +#include "esp_random.h" +#include "esp_timer.h" +#include "esp_wpa.h" +#include "periph_ctrl.h" +#include "rom/ets_sys.h" +#include "soc/soc_caps.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define PHY_RF_MASK ((1 << PHY_BT_MODULE) | (1 << PHY_WIFI_MODULE)) + +#define WIFI_CONNECT_TIMEOUT CONFIG_ESPRESSIF_WIFI_CONNECT_TIMEOUT + +#define TIMER_INITIALIZED_VAL (0x5aa5a55a) + +#define ESP_WIFI_11B_MAX_BITRATE 11 +#define ESP_WIFI_11G_MAX_BITRATE 54 +#define ESP_WIFI_11N_MCS7_HT20_BITRATE 72 +#define ESP_WIFI_11N_MCS7_HT40_BITRATE 150 + +#ifndef CONFIG_EXAMPLE_WIFI_LISTEN_INTERVAL +#define CONFIG_EXAMPLE_WIFI_LISTEN_INTERVAL 3 +#endif + +#define DEFAULT_LISTEN_INTERVAL CONFIG_EXAMPLE_WIFI_LISTEN_INTERVAL + +#define RTC_CLK_CAL_FRACT 19 /* Number of fractional bits in values returned by rtc_clk_cal */ + +#define ets_timer _ETSTIMER_ + +/* CONFIG_POWER_SAVE_MODEM */ + +#if defined(CONFIG_ESPRESSIF_POWER_SAVE_MIN_MODEM) +# define DEFAULT_PS_MODE WIFI_PS_MIN_MODEM +#elif defined(CONFIG_ESPRESSIF_POWER_SAVE_MAX_MODEM) +# define DEFAULT_PS_MODE WIFI_PS_MAX_MODEM +#elif defined(CONFIG_ESPRESSIF_POWER_SAVE_NONE) +# define DEFAULT_PS_MODE WIFI_PS_NONE +#else +# define DEFAULT_PS_MODE WIFI_PS_NONE +#endif + +#define ESP_MAX_PRIORITIES (25) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* Wi-Fi Station state */ + +enum wifi_sta_state +{ + WIFI_STA_STATE_NULL, + WIFI_STA_STATE_START, + WIFI_STA_STATE_CONNECT, + WIFI_STA_STATE_DISCONNECT, + WIFI_STA_STATE_STOP +}; + +/* Wi-Fi interrupt adapter private data */ + +struct irq_adpt +{ + void (*func)(void *arg); /* Interrupt callback function */ + void *arg; /* Interrupt private data */ +}; + +/* Wi-Fi message queue private data */ + +struct mq_adpt +{ + struct file mq; /* Message queue handle */ + uint32_t msgsize; /* Message size */ + char name[16]; /* Message queue name */ +}; + +/* Wi-Fi time private data */ + +struct time_adpt +{ + time_t sec; /* Second value */ + suseconds_t usec; /* Micro second value */ +}; + +/* Wi-Fi event private data */ + +struct evt_adpt +{ + sq_entry_t entry; /* Sequence entry */ + int32_t id; /* Event ID */ + uint8_t buf[0]; /* Event private data */ +}; + +/* Wi-Fi event notification private data */ + +struct wifi_notify +{ + bool assigned; /* Flag indicate if it is used */ + pid_t pid; /* Signal's target thread PID */ + struct sigevent event; /* Signal event private data */ + struct sigwork_s work; /* Signal work private data */ +}; + +/* Wi-Fi NVS private data */ + +struct nvs_adpt +{ + char *index_name; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static bool wifi_env_is_chip(void); +static void wifi_set_intr(int32_t cpu_no, uint32_t intr_source, + uint32_t intr_num, int32_t intr_prio); +static void wifi_clear_intr(uint32_t intr_source, uint32_t intr_num); +static void esp_set_isr(int32_t n, void *f, void *arg); +static void esp32s2_ints_on(uint32_t mask); +static void esp32s2_ints_off(uint32_t mask); +static bool wifi_is_from_isr(void); +static void *esp_spin_lock_create(void); +static void esp_spin_lock_delete(void *lock); +static uint32_t esp_wifi_int_disable(void *wifi_int_mux); +static void esp_wifi_int_restore(void *wifi_int_mux, uint32_t tmp); +static void esp_task_yield_from_isr(void); +static void *esp_semphr_create(uint32_t max, uint32_t init); +static void esp_semphr_delete(void *semphr); +static int32_t esp_semphr_take(void *semphr, uint32_t block_time_tick); +static int32_t esp_semphr_give(void *semphr); +static void *esp_thread_semphr_get(void); +static void *esp_mutex_create(void); +static void *esp_recursive_mutex_create(void); +static void esp_mutex_delete(void *mutex_data); +static int32_t esp_mutex_lock(void *mutex_data); +static int32_t esp_mutex_unlock(void *mutex_data); +static void *esp_queue_create(uint32_t queue_len, uint32_t item_size); +static void esp_queue_delete(void *queue); +static int32_t esp_queue_send(void *queue, void *item, + uint32_t block_time_tick); +static int32_t esp_queue_send_from_isr(void *queue, void *item, void *hptw); +static int32_t esp_queue_send_to_back(void *queue, void *item, + uint32_t block_time_tick); +static int32_t esp_queue_send_to_front(void *queue, void *item, + uint32_t block_time_tick); +static int32_t esp_queue_recv(void *queue, void *item, + uint32_t block_time_tick); +static uint32_t esp_queue_msg_waiting(void *queue); +static void *esp_event_group_create(void); +static void esp_event_group_delete(void *event); +static uint32_t esp_event_group_set_bits(void *event, uint32_t bits); +static uint32_t esp_event_group_clear_bits(void *event, uint32_t bits); +static uint32_t esp_event_group_wait_bits(void *event, + uint32_t bits_to_wait_for, + int32_t clear_on_exit, + int32_t wait_for_all_bits, + uint32_t block_time_tick); +static int32_t esp_task_create_pinned_to_core(void *task_func, + const char *name, + uint32_t stack_depth, + void *param, + uint32_t prio, + void *task_handle, + uint32_t core_id); +static int32_t esp_task_create(void *task_func, const char *name, + uint32_t stack_depth, void *param, + uint32_t prio, void *task_handle); +static void esp_task_delete(void *task_handle); +static void esp_task_delay(uint32_t tick); +static int32_t esp_task_ms_to_tick(uint32_t ms); +static void *esp_task_get_current_task(void); +static int32_t esp_task_get_max_priority(void); +static void *esp_malloc(uint32_t size); +static void esp_free(void *ptr); +static uint32_t esp_get_free_heap_size(void); +static uint32_t esp_rand(void); +static void wifi_apb80m_request(void); +static void wifi_apb80m_release(void); +static void IRAM_ATTR esp_empty_wrapper(void); +static void esp_phy_enable_wrapper(void); +static void esp_phy_disable_wrapper(void); +static int32_t esp_wifi_read_mac(uint8_t *mac, uint32_t type); +static void esp_timer_arm(void *timer, uint32_t tmout, bool repeat); +static void esp_timer_disarm(void *timer); +static void esp32s2_timer_done(void *timer); +static void esp_timer_setfn(void *timer, void *pfunction, void *parg); +static void esp_timer_arm_us(void *timer, uint32_t us, bool repeat); +static void wifi_reset_mac(void); +static void wifi_clock_enable(void); +static void wifi_clock_disable(void); +static int64_t esp32s2_timer_get_time(void); +static int32_t esp_nvs_set_i8(uint32_t handle, const char *key, + int8_t value); +static int32_t esp_nvs_get_i8(uint32_t handle, const char *key, + int8_t *out_value); +static int32_t esp_nvs_set_u8(uint32_t handle, const char *key, + uint8_t value); +static int32_t esp_nvs_get_u8(uint32_t handle, const char *key, + uint8_t *out_value); +static int32_t esp_nvs_set_u16(uint32_t handle, const char *key, + uint16_t value); +static int32_t esp_nvs_get_u16(uint32_t handle, const char *key, + uint16_t *out_value); +static int32_t esp_nvs_open(const char *name, uint32_t open_mode, + uint32_t *out_handle); +static void esp_nvs_close(uint32_t handle); +static int32_t esp_nvs_commit(uint32_t handle); +static int32_t esp_nvs_set_blob(uint32_t handle, const char *key, + const void *value, size_t length); +static int32_t esp_nvs_get_blob(uint32_t handle, const char *key, + void *out_value, size_t *length); +static int32_t esp_nvs_erase_key(uint32_t handle, const char *key); +static int32_t esp_get_random(uint8_t *buf, size_t len); +static int32_t esp_get_time(void *t); +static uint32_t esp_clk_slowclk_cal_get_wrapper(void); +static void esp_log_writev_wrapper(uint32_t level, const char *tag, + const char *format, va_list args); +static void esp_log_write_wrapper(uint32_t level, + const char *tag, + const char *format, ...); +static void *esp_malloc_internal(size_t size); +static void *esp_realloc_internal(void *ptr, size_t size); +static void *esp_calloc_internal(size_t n, size_t size); +static void *esp_zalloc_internal(size_t size); +static void *esp_wifi_malloc(size_t size); +static void *esp_wifi_realloc(void *ptr, size_t size); +static void *esp_wifi_calloc(size_t n, size_t size); +static void *esp_wifi_zalloc(size_t size); +static void *esp_wifi_create_queue(int32_t queue_len, int32_t item_size); +static void esp_wifi_delete_queue(void *queue); +static int coex_init_wrapper(void); +static void coex_deinit_wrapper(void); +static int coex_enable_wrapper(void); +static void coex_disable_wrapper(void); +static uint32_t coex_status_get_wrapper(void); +static int32_t coex_wifi_request_wrapper(uint32_t event, uint32_t latency, + uint32_t duration); +static int32_t coex_wifi_release_wrapper(uint32_t event); +static unsigned long esp_random_ulong(void); +static int coex_wifi_channel_set_wrapper(uint8_t primary, uint8_t secondary); +static int coex_event_duration_get_wrapper(uint32_t event, + uint32_t *duration); +static int coex_pti_get_wrapper(uint32_t event, uint8_t *pti); +static void coex_schm_status_bit_clear_wrapper(uint32_t type, + uint32_t status); +static void coex_schm_status_bit_set_wrapper(uint32_t type, + uint32_t status); +static int coex_schm_interval_set_wrapper(uint32_t interval); +static uint32_t coex_schm_interval_get_wrapper(void); +static uint8_t coex_schm_curr_period_get_wrapper(void); +static void *coex_schm_curr_phase_get_wrapper(void); +static int coex_register_start_cb_wrapper(int (* cb)(void)); +static int coex_schm_process_restart_wrapper(void); +static int coex_schm_register_cb_wrapper(int type, int(*cb)(int)); +static int coex_schm_flexible_period_set_wrapper(uint8_t period); +static uint8_t coex_schm_flexible_period_get_wrapper(void); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Wi-Fi event private data */ + +static struct work_s g_wifi_evt_work; +static sq_queue_t g_wifi_evt_queue; +static struct wifi_notify g_wifi_notify[WIFI_ADPT_EVT_MAX]; +static mutex_t g_wifiexcl_lock = NXMUTEX_INITIALIZER; + +/* Wi-Fi adapter reference */ + +static int g_wifi_ref; + +#ifdef ESPRESSIF_WLAN_HAS_STA + +/* If reconnect automatically */ + +static bool g_sta_reconnect; + +/* If Wi-Fi sta starts */ + +static bool g_sta_started; + +/* If Wi-Fi sta connected */ + +static bool g_sta_connected; + +/* Wi-Fi station TX done callback function */ + +static wifi_txdone_cb_t g_sta_txdone_cb; + +/* Wi-Fi interface configuration */ + +static wifi_config_t g_sta_wifi_cfg; + +#endif /* ESPRESSIF_WLAN_HAS_STA */ + +#ifdef ESPRESSIF_WLAN_HAS_SOFTAP + +/* If Wi-Fi SoftAP starts */ + +static bool g_softap_started; + +/* Wi-Fi SoftAP TX done callback function */ + +static wifi_txdone_cb_t g_softap_txdone_cb; + +/* Wi-Fi interface configuration */ + +static wifi_config_t g_softap_wifi_cfg; + +#endif /* ESPRESSIF_WLAN_HAS_SOFTAP */ + +/* Device specific lock */ + +static spinlock_t g_lock; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* Wi-Fi OS adapter data */ + +wifi_osi_funcs_t g_wifi_osi_funcs = +{ + ._version = ESP_WIFI_OS_ADAPTER_VERSION, + ._env_is_chip = wifi_env_is_chip, + ._set_intr = wifi_set_intr, + ._clear_intr = wifi_clear_intr, + ._set_isr = esp_set_isr, + ._ints_on = esp32s2_ints_on, + ._ints_off = esp32s2_ints_off, + ._is_from_isr = wifi_is_from_isr, + ._spin_lock_create = esp_spin_lock_create, + ._spin_lock_delete = esp_spin_lock_delete, + ._wifi_int_disable = esp_wifi_int_disable, + ._wifi_int_restore = esp_wifi_int_restore, + ._task_yield_from_isr = esp_task_yield_from_isr, + ._semphr_create = esp_semphr_create, + ._semphr_delete = esp_semphr_delete, + ._semphr_take = esp_semphr_take, + ._semphr_give = esp_semphr_give, + ._wifi_thread_semphr_get = esp_thread_semphr_get, + ._mutex_create = esp_mutex_create, + ._recursive_mutex_create = esp_recursive_mutex_create, + ._mutex_delete = esp_mutex_delete, + ._mutex_lock = esp_mutex_lock, + ._mutex_unlock = esp_mutex_unlock, + ._queue_create = esp_queue_create, + ._queue_delete = esp_queue_delete, + ._queue_send = esp_queue_send, + ._queue_send_from_isr = esp_queue_send_from_isr, + ._queue_send_to_back = esp_queue_send_to_back, + ._queue_send_to_front = esp_queue_send_to_front, + ._queue_recv = esp_queue_recv, + ._queue_msg_waiting = esp_queue_msg_waiting, + ._event_group_create = esp_event_group_create, + ._event_group_delete = esp_event_group_delete, + ._event_group_set_bits = esp_event_group_set_bits, + ._event_group_clear_bits = esp_event_group_clear_bits, + ._event_group_wait_bits = esp_event_group_wait_bits, + ._task_create_pinned_to_core = esp_task_create_pinned_to_core, + ._task_create = esp_task_create, + ._task_delete = esp_task_delete, + ._task_delay = esp_task_delay, + ._task_ms_to_tick = esp_task_ms_to_tick, + ._task_get_current_task = esp_task_get_current_task, + ._task_get_max_priority = esp_task_get_max_priority, + ._malloc = esp_malloc, + ._free = esp_free, + ._event_post = esp_event_post, + ._get_free_heap_size = esp_get_free_heap_size, + ._rand = esp_rand, + ._dport_access_stall_other_cpu_start_wrap = esp_empty_wrapper, + ._dport_access_stall_other_cpu_end_wrap = esp_empty_wrapper, + ._wifi_apb80m_request = wifi_apb80m_request, + ._wifi_apb80m_release = wifi_apb80m_release, + ._phy_disable = esp_phy_disable_wrapper, + ._phy_enable = esp_phy_enable_wrapper, + ._phy_common_clock_enable = esp_phy_common_clock_enable, + ._phy_common_clock_disable = esp_phy_common_clock_disable, + ._phy_update_country_info = esp_phy_update_country_info, + ._read_mac = esp_wifi_read_mac, + ._timer_arm = esp_timer_arm, + ._timer_disarm = esp_timer_disarm, + ._timer_done = esp32s2_timer_done, + ._timer_setfn = esp_timer_setfn, + ._timer_arm_us = esp_timer_arm_us, + ._wifi_reset_mac = wifi_reset_mac, + ._wifi_clock_enable = wifi_clock_enable, + ._wifi_clock_disable = wifi_clock_disable, + ._wifi_rtc_enable_iso = esp_empty_wrapper, + ._wifi_rtc_disable_iso = esp_empty_wrapper, + ._esp_timer_get_time = esp32s2_timer_get_time, + ._nvs_set_i8 = esp_nvs_set_i8, + ._nvs_get_i8 = esp_nvs_get_i8, + ._nvs_set_u8 = esp_nvs_set_u8, + ._nvs_get_u8 = esp_nvs_get_u8, + ._nvs_set_u16 = esp_nvs_set_u16, + ._nvs_get_u16 = esp_nvs_get_u16, + ._nvs_open = esp_nvs_open, + ._nvs_close = esp_nvs_close, + ._nvs_commit = esp_nvs_commit, + ._nvs_set_blob = esp_nvs_set_blob, + ._nvs_get_blob = esp_nvs_get_blob, + ._nvs_erase_key = esp_nvs_erase_key, + ._get_random = esp_get_random, + ._get_time = esp_get_time, + ._random = esp_random_ulong, + ._slowclk_cal_get = esp_clk_slowclk_cal_get_wrapper, + ._log_write = esp_log_write_wrapper, + ._log_writev = esp_log_writev_wrapper, + ._log_timestamp = esp_log_timestamp, + ._malloc_internal = esp_malloc_internal, + ._realloc_internal = esp_realloc_internal, + ._calloc_internal = esp_calloc_internal, + ._zalloc_internal = esp_zalloc_internal, + ._wifi_malloc = esp_wifi_malloc, + ._wifi_realloc = esp_wifi_realloc, + ._wifi_calloc = esp_wifi_calloc, + ._wifi_zalloc = esp_wifi_zalloc, + ._wifi_create_queue = esp_wifi_create_queue, + ._wifi_delete_queue = esp_wifi_delete_queue, + ._coex_init = coex_init_wrapper, + ._coex_deinit = coex_deinit_wrapper, + ._coex_enable = coex_enable_wrapper, + ._coex_disable = coex_disable_wrapper, + ._coex_status_get = coex_status_get_wrapper, + ._coex_wifi_request = coex_wifi_request_wrapper, + ._coex_wifi_release = coex_wifi_release_wrapper, + ._coex_wifi_channel_set = coex_wifi_channel_set_wrapper, + ._coex_event_duration_get = coex_event_duration_get_wrapper, + ._coex_pti_get = coex_pti_get_wrapper, + ._coex_schm_status_bit_clear = coex_schm_status_bit_clear_wrapper, + ._coex_schm_status_bit_set = coex_schm_status_bit_set_wrapper, + ._coex_schm_interval_set = coex_schm_interval_set_wrapper, + ._coex_schm_interval_get = coex_schm_interval_get_wrapper, + ._coex_schm_curr_period_get = coex_schm_curr_period_get_wrapper, + ._coex_schm_curr_phase_get = coex_schm_curr_phase_get_wrapper, + ._coex_register_start_cb = coex_register_start_cb_wrapper, + ._coex_schm_process_restart = coex_schm_process_restart_wrapper, + ._coex_schm_register_cb = coex_schm_register_cb_wrapper, + ._coex_schm_flexible_period_set = coex_schm_flexible_period_set_wrapper, + ._coex_schm_flexible_period_get = coex_schm_flexible_period_get_wrapper, + ._magic = ESP_WIFI_OS_ADAPTER_MAGIC, +}; + +/* Wi-Fi TAG string data */ + +ESP_EVENT_DEFINE_BASE(WIFI_EVENT); + +/**************************************************************************** + * Private Functions and Public Functions only used by libraries + ****************************************************************************/ + +/**************************************************************************** + * Name: osi_errno_trans + * + * Description: + * Transform from nuttx Os error code to Wi-Fi adapter error code + * + * Input Parameters: + * ret - NuttX error code + * + * Returned Value: + * Wi-Fi adapter error code + * + ****************************************************************************/ + +static inline int32_t osi_errno_trans(int ret) +{ + if (!ret) + { + return true; + } + else + { + return false; + } +} + +/**************************************************************************** + * Name: wifi_errno_trans + * + * Description: + * Transform from ESP Wi-Fi error code to NuttX error code + * + * Input Parameters: + * ret - ESP Wi-Fi error code + * + * Returned Value: + * NuttX error code + * + ****************************************************************************/ + +static int32_t wifi_errno_trans(int ret) +{ + int wifierr; + + /* Unmask component error bits */ + + wifierr = ret & 0xfff; + + if (wifierr == ESP_OK) + { + return OK; + } + else if (wifierr == ESP_ERR_NO_MEM) + { + return -ENOMEM; + } + else if (wifierr == ESP_ERR_INVALID_ARG) + { + return -EINVAL; + } + else if (wifierr == ESP_ERR_INVALID_STATE) + { + return -EIO; + } + else if (wifierr == ESP_ERR_INVALID_SIZE) + { + return -EINVAL; + } + else if (wifierr == ESP_ERR_NOT_FOUND) + { + return -ENOSYS; + } + else if (wifierr == ESP_ERR_NOT_SUPPORTED) + { + return -ENOSYS; + } + else if (wifierr == ESP_ERR_TIMEOUT) + { + return -ETIMEDOUT; + } + else if (wifierr == ESP_ERR_INVALID_MAC) + { + return -EINVAL; + } + else + { + return ERROR; + } +} + +/**************************************************************************** + * Name: esp_int_adpt_cb + * + * Description: + * Wi-Fi interrupt adapter callback function + * + * Input Parameters: + * arg - interrupt adapter private data + * + * Returned Value: + * 0 on success + * + ****************************************************************************/ + +static int esp_int_adpt_cb(int irq, void *context, void *arg) +{ + struct irq_adpt *adapter = (struct irq_adpt *)arg; + + adapter->func(adapter->arg); + + return 0; +} + +/**************************************************************************** + * Name: esp_thread_semphr_free + * + * Description: + * Delete thread self's semaphore + * + * Input Parameters: + * semphr - Semaphore data pointer + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp_thread_semphr_free(void *semphr) +{ + if (semphr) + { + esp_semphr_delete(semphr); + } +} + +/**************************************************************************** + * Name: esp_update_time + * + * Description: + * Transform ticks to time and add this time to timespec value + * + * Input Parameters: + * timespec - Input timespec data pointer + * ticks - System ticks + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp_update_time(struct timespec *timespec, uint32_t ticks) +{ + uint32_t tmp; + + tmp = TICK2SEC(ticks); + timespec->tv_sec += tmp; + + ticks -= SEC2TICK(tmp); + tmp = TICK2NSEC(ticks); + + timespec->tv_nsec += tmp; +} + +/**************************************************************************** + * Name: esp_wifi_lock + * + * Description: + * Lock or unlock the event process + * + * Input Parameters: + * lock - true: Lock event process, false: unlock event process + * + * Returned Value: + * The result of lock or unlock the event process + * + ****************************************************************************/ + +static int esp_wifi_lock(bool lock) +{ + int ret; + + if (lock) + { + ret = nxmutex_lock(&g_wifiexcl_lock); + if (ret < 0) + { + wlinfo("Failed to lock Wi-Fi ret=%d\n", ret); + } + } + else + { + ret = nxmutex_unlock(&g_wifiexcl_lock); + if (ret < 0) + { + wlinfo("Failed to unlock Wi-Fi ret=%d\n", ret); + } + } + + return ret; +} + +/**************************************************************************** + * Name: esp_set_isr + * + * Description: + * Register interrupt function + * + * Input Parameters: + * n - Interrupt ID + * f - Interrupt function + * arg - Function private data + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp_set_isr(int32_t n, void *f, void *arg) +{ + int ret; + uint32_t tmp; + struct irq_adpt *adapter; + int irq = n + XTENSA_IRQ_FIRSTPERIPH; + + wlinfo("n=%d f=%p arg=%p", n, f, arg); + + if (g_irqvector[irq].handler && + g_irqvector[irq].handler != irq_unexpected_isr) + { + wlinfo("irq=%d has been set handler=%p\n", irq, + g_irqvector[irq].handler); + return; + } + + tmp = sizeof(struct irq_adpt); + adapter = kmm_malloc(tmp); + if (!adapter) + { + wlerr("Failed to alloc %d memory\n", tmp); + PANIC(); + return; + } + + adapter->func = f; + adapter->arg = arg; + + ret = irq_attach(ESP32S2_IRQ_MAC, esp_int_adpt_cb, adapter); + if (ret) + { + wlerr("Failed to attach IRQ %d\n", irq); + PANIC(); + return; + } + + ret = irq_attach(ESP32S2_IRQ_PWR, esp_int_adpt_cb, adapter); + if (ret) + { + wlerr("Failed to attach IRQ %d\n", irq); + PANIC(); + return; + } +} + +/**************************************************************************** + * Name: esp32s2_ints_on + * + * Description: + * Enable Wi-Fi interrupt + * + * Input Parameters: + * mask - No mean + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp32s2_ints_on(uint32_t mask) +{ + int irq = __builtin_ffs(mask) - 1; + + wlinfo("INFO mask=%08x irq=%d\n", mask, irq); + + up_enable_irq(ESP32S2_IRQ_MAC); + up_enable_irq(ESP32S2_IRQ_PWR); +} + +/**************************************************************************** + * Name: esp32s2_ints_off + * + * Description: + * Disable Wi-Fi interrupt + * + * Input Parameters: + * mask - No mean + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp32s2_ints_off(uint32_t mask) +{ + uint32_t irq = __builtin_ffs(mask) - 1; + + wlinfo("INFO mask=%08x irq=%d\n", mask, irq); + + up_disable_irq(ESP32S2_IRQ_MAC); + up_disable_irq(ESP32S2_IRQ_PWR); +} + +/**************************************************************************** + * Name: wifi_is_from_isr + * + * Description: + * Check current is in interrupt + * + * Input Parameters: + * None + * + * Returned Value: + * true if in interrupt or false if not + * + ****************************************************************************/ + +static bool IRAM_ATTR wifi_is_from_isr(void) +{ + return up_interrupt_context(); +} + +/**************************************************************************** + * Name: esp_spin_lock_create + * + * Description: + * Create spin lock in SMP mode + * + * Input Parameters: + * None + * + * Returned Value: + * Spin lock data pointer + * + ****************************************************************************/ + +static void *esp_spin_lock_create(void) +{ + spinlock_t *lock; + int tmp; + + tmp = sizeof(*lock); + lock = kmm_malloc(tmp); + if (!lock) + { + wlerr("Failed to alloc %d memory\n", tmp); + DEBUGPANIC(); + } + + spin_initialize(lock, SP_UNLOCKED); + + return lock; +} + +/**************************************************************************** + * Name: esp_spin_lock_delete + * + * Description: + * Delete spin lock + * + * Input Parameters: + * lock - Spin lock data pointer + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp_spin_lock_delete(void *lock) +{ + kmm_free(lock); +} + +/**************************************************************************** + * Name: esp_wifi_int_disable + * + * Description: + * Enter critical section by disabling interrupts and taking the spin lock + * if in SMP mode. + * + * Input Parameters: + * wifi_int_mux - Spin lock data pointer + * + * Returned Value: + * CPU PS value. + * + ****************************************************************************/ + +static uint32_t IRAM_ATTR esp_wifi_int_disable(void *wifi_int_mux) +{ + irqstate_t flags; + + flags = spin_lock_irqsave((spinlock_t *)wifi_int_mux); + + return (uint32_t)flags; +} + +/**************************************************************************** + * Name: esp_wifi_int_restore + * + * Description: + * Exit from critical section by enabling interrupts and releasing the spin + * lock if in SMP mode. + * + * Input Parameters: + * wifi_int_mux - Spin lock data pointer + * tmp - CPU PS value. + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void IRAM_ATTR esp_wifi_int_restore(void *wifi_int_mux, uint32_t tmp) +{ + irqstate_t flags = (irqstate_t)tmp; + + spin_unlock_irqrestore((spinlock_t *)wifi_int_mux, flags); +} + +/**************************************************************************** + * Name: esp_task_yield_from_isr + * + * Description: + * Perform a solicited context switch on FreeRTOS. Do nothing in NuttX. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void IRAM_ATTR esp_task_yield_from_isr(void) +{ +} + +/**************************************************************************** + * Name: esp_semphr_create + * + * Description: + * Create and initialize semaphore + * + * Input Parameters: + * max - No mean + * init - semaphore initialization value + * + * Returned Value: + * Semaphore data pointer + * + ****************************************************************************/ + +static void *esp_semphr_create(uint32_t max, uint32_t init) +{ + int ret; + sem_t *sem; + int tmp; + + tmp = sizeof(sem_t); + sem = kmm_malloc(tmp); + if (!sem) + { + wlerr("Failed to alloc %d memory\n", tmp); + return NULL; + } + + ret = nxsem_init(sem, 0, init); + if (ret) + { + wlerr("Failed to initialize sem error=%d\n", ret); + kmm_free(sem); + return NULL; + } + + return sem; +} + +/**************************************************************************** + * Name: esp_semphr_delete + * + * Description: + * Delete semaphore + * + * Input Parameters: + * semphr - Semaphore data pointer + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp_semphr_delete(void *semphr) +{ + sem_t *sem = (sem_t *)semphr; + + nxsem_destroy(sem); + kmm_free(sem); +} + +/**************************************************************************** + * Name: esp_semphr_take + * + * Description: + * Wait semaphore within a certain period of time + * + * Input Parameters: + * semphr - Semaphore data pointer + * block_time_tick - Wait system ticks + * + * Returned Value: + * True if success or false if fail + * + ****************************************************************************/ + +static int32_t esp_semphr_take(void *semphr, uint32_t block_time_tick) +{ + int ret; + sem_t *sem = (sem_t *)semphr; + + if (block_time_tick == OSI_FUNCS_TIME_BLOCKING) + { + ret = nxsem_wait(sem); + } + else + { + if (block_time_tick > 0) + { + ret = nxsem_tickwait(sem, block_time_tick); + } + else + { + ret = nxsem_trywait(sem); + } + } + + if (ret) + { + wlerr("ERROR: Failed to wait sem in %u ticks. Error=%d\n", + block_time_tick, ret); + } + + return osi_errno_trans(ret); +} + +/**************************************************************************** + * Name: esp_semphr_give + * + * Description: + * Post semaphore + * + * Input Parameters: + * semphr - Semaphore data pointer + * + * Returned Value: + * True if success or false if fail + * + ****************************************************************************/ + +static int32_t esp_semphr_give(void *semphr) +{ + int ret; + sem_t *sem = (sem_t *)semphr; + + ret = nxsem_post(sem); + if (ret) + { + wlerr("Failed to post sem error=%d\n", ret); + } + + return osi_errno_trans(ret); +} + +/**************************************************************************** + * Name: esp_thread_semphr_get + * + * Description: + * Get thread self's semaphore + * + * Input Parameters: + * None + * + * Returned Value: + * Semaphore data pointer + * + ****************************************************************************/ + +static void *esp_thread_semphr_get(void) +{ + static int wifi_task_key = -1; + int ret; + void *sem; + + if (wifi_task_key < 0) + { + ret = task_tls_alloc(esp_thread_semphr_free); + if (ret < 0) + { + wlerr("Failed to create task local key\n"); + return NULL; + } + + wifi_task_key = ret; + } + + sem = (void *)task_tls_get_value(wifi_task_key); + if (sem == NULL) + { + sem = esp_semphr_create(1, 0); + if (!sem) + { + wlerr("Failed to create semaphore\n"); + return NULL; + } + + ret = task_tls_set_value(wifi_task_key, (uintptr_t)sem); + if (ret != OK) + { + wlerr("Failed to save semaphore on task local storage: %d\n", ret); + esp_semphr_delete(sem); + return NULL; + } + } + + return sem; +} + +/**************************************************************************** + * Name: esp_mutex_create + * + * Description: + * Create mutex + * + * Input Parameters: + * None + * + * Returned Value: + * Mutex data pointer + * + ****************************************************************************/ + +static void *esp_mutex_create(void) +{ + int ret; + pthread_mutex_t *mutex; + int tmp; + + tmp = sizeof(pthread_mutex_t); + mutex = kmm_malloc(tmp); + if (!mutex) + { + wlerr("Failed to alloc %d memory\n", tmp); + return NULL; + } + + ret = pthread_mutex_init(mutex, NULL); + if (ret) + { + wlerr("Failed to initialize mutex error=%d\n", ret); + kmm_free(mutex); + return NULL; + } + + return mutex; +} + +/**************************************************************************** + * Name: esp_recursive_mutex_create + * + * Description: + * Create recursive mutex + * + * Input Parameters: + * None + * + * Returned Value: + * Recursive mutex data pointer + * + ****************************************************************************/ + +static void *esp_recursive_mutex_create(void) +{ + int ret; + pthread_mutex_t *mutex; + pthread_mutexattr_t attr; + int tmp; + + ret = pthread_mutexattr_init(&attr); + if (ret) + { + wlerr("Failed to initialize attr error=%d\n", ret); + return NULL; + } + + ret = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + if (ret) + { + wlerr("Failed to set attr type error=%d\n", ret); + return NULL; + } + + tmp = sizeof(pthread_mutex_t); + mutex = kmm_malloc(tmp); + if (!mutex) + { + wlerr("Failed to alloc %d memory\n", tmp); + return NULL; + } + + ret = pthread_mutex_init(mutex, &attr); + if (ret) + { + wlerr("Failed to initialize mutex error=%d\n", ret); + kmm_free(mutex); + return NULL; + } + + return mutex; +} + +/**************************************************************************** + * Name: esp_mutex_delete + * + * Description: + * Delete mutex + * + * Input Parameters: + * mutex_data - mutex data pointer + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp_mutex_delete(void *mutex_data) +{ + pthread_mutex_t *mutex = (pthread_mutex_t *)mutex_data; + + pthread_mutex_destroy(mutex); + kmm_free(mutex); +} + +/**************************************************************************** + * Name: esp_mutex_lock + * + * Description: + * Lock mutex + * + * Input Parameters: + * mutex_data - mutex data pointer + * + * Returned Value: + * True if success or false if fail + * + ****************************************************************************/ + +static int32_t esp_mutex_lock(void *mutex_data) +{ + int ret; + pthread_mutex_t *mutex = (pthread_mutex_t *)mutex_data; + + ret = pthread_mutex_lock(mutex); + if (ret) + { + wlerr("Failed to lock mutex error=%d\n", ret); + } + + return osi_errno_trans(ret); +} + +/**************************************************************************** + * Name: esp_mutex_unlock + * + * Description: + * Unlock mutex + * + * Input Parameters: + * mutex_data - mutex data pointer + * + * Returned Value: + * True if success or false if fail + * + ****************************************************************************/ + +static int32_t esp_mutex_unlock(void *mutex_data) +{ + int ret; + pthread_mutex_t *mutex = (pthread_mutex_t *)mutex_data; + + ret = pthread_mutex_unlock(mutex); + if (ret) + { + wlerr("Failed to unlock mutex error=%d\n", ret); + } + + return osi_errno_trans(ret); +} + +/**************************************************************************** + * Name: esp_queue_create + * + * Description: + * Create message queue + * + * Input Parameters: + * queue_len - queue message number + * item_size - message size + * + * Returned Value: + * Message queue data pointer + * + ****************************************************************************/ + +static void *esp_queue_create(uint32_t queue_len, uint32_t item_size) +{ + struct mq_attr attr; + struct mq_adpt *mq_adpt; + int ret; + + mq_adpt = kmm_malloc(sizeof(struct mq_adpt)); + if (!mq_adpt) + { + wlerr("Failed to kmm_malloc\n"); + return NULL; + } + + snprintf(mq_adpt->name, sizeof(mq_adpt->name), + "/tmp/%p", mq_adpt); + + attr.mq_maxmsg = queue_len; + attr.mq_msgsize = item_size; + attr.mq_curmsgs = 0; + attr.mq_flags = 0; + + ret = file_mq_open(&mq_adpt->mq, mq_adpt->name, + O_RDWR | O_CREAT, 0644, &attr); + if (ret < 0) + { + wlerr("Failed to create mqueue\n"); + kmm_free(mq_adpt); + return NULL; + } + + mq_adpt->msgsize = item_size; + + return (void *)mq_adpt; +} + +/**************************************************************************** + * Name: esp_queue_delete + * + * Description: + * Delete message queue + * + * Input Parameters: + * queue - Message queue data pointer + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp_queue_delete(void *queue) +{ + struct mq_adpt *mq_adpt = (struct mq_adpt *)queue; + + file_mq_close(&mq_adpt->mq); + file_mq_unlink(mq_adpt->name); + kmm_free(mq_adpt); +} + +/**************************************************************************** + * Name: esp_queue_send_generic + * + * Description: + * Generic send message to queue within a certain period of time + * + * Input Parameters: + * queue - Message queue data pointer + * item - Message data pointer + * ticks - Wait ticks + * prio - Message priority + * + * Returned Value: + * True if success or false if fail + * + ****************************************************************************/ + +static int32_t esp_queue_send_generic(void *queue, void *item, + uint32_t ticks, int prio) +{ + int ret; + struct timespec timeout; + struct mq_adpt *mq_adpt = (struct mq_adpt *)queue; + + if (ticks == OSI_FUNCS_TIME_BLOCKING || ticks == 0) + { + /* Wi-Fi interrupt function will call this adapter function to send + * message to message queue, so here we should call kernel API + * instead of application API + */ + + ret = file_mq_send(&mq_adpt->mq, (const char *)item, + mq_adpt->msgsize, prio); + if (ret < 0) + { + wlerr("Failed to send message to mqueue error=%d\n", + ret); + } + } + else + { + ret = clock_gettime(CLOCK_REALTIME, &timeout); + if (ret < 0) + { + wlerr("Failed to get time\n"); + return false; + } + + if (ticks) + { + esp_update_time(&timeout, ticks); + } + + ret = file_mq_timedsend(&mq_adpt->mq, (const char *)item, + mq_adpt->msgsize, prio, &timeout); + if (ret < 0) + { + wlerr("Failed to timedsend message to mqueue error=%d\n", + ret); + } + } + + return osi_errno_trans(ret); +} + +/**************************************************************************** + * Name: esp_queue_send + * + * Description: + * Send message of low priority to queue within a certain period of time + * + * Input Parameters: + * queue - Message queue data pointer + * item - Message data pointer + * ticks - Wait ticks + * + * Returned Value: + * True if success or false if fail + * + ****************************************************************************/ + +static int32_t esp_queue_send(void *queue, void *item, uint32_t ticks) +{ + return esp_queue_send_generic(queue, item, ticks, 0); +} + +/**************************************************************************** + * Name: esp_queue_send_from_isr + * + * Description: + * Send message of low priority to queue in ISR within + * a certain period of time + * + * Input Parameters: + * queue - Message queue data pointer + * item - Message data pointer + * hptw - Unused. + * + * Returned Value: + * True if success or false if fail + * + ****************************************************************************/ + +static int32_t esp_queue_send_from_isr(void *queue, void *item, void *hptw) +{ + *(int *)hptw = 0; + + return esp_queue_send_generic(queue, item, 0, 0); +} + +/**************************************************************************** + * Name: esp_queue_send_to_back + * + * Description: + * Send message of low priority to queue within a certain period of time + * + * Input Parameters: + * queue - Message queue data pointer + * item - Message data pointer + * ticks - Wait ticks + * + * Returned Value: + * True if success or false if fail + * + ****************************************************************************/ + +static int32_t esp_queue_send_to_back(void *queue, void *item, + uint32_t ticks) +{ + return esp_queue_send_generic(queue, item, ticks, 0); +} + +/**************************************************************************** + * Name: esp_queue_send_from_to_front + * + * Description: + * Send message of high priority to queue within a certain period of time + * + * Input Parameters: + * queue - Message queue data pointer + * item - Message data pointer + * ticks - Wait ticks + * + * Returned Value: + * True if success or false if fail + * + ****************************************************************************/ + +static int32_t esp_queue_send_to_front(void *queue, void *item, + uint32_t ticks) +{ + return esp_queue_send_generic(queue, item, ticks, 1); +} + +/**************************************************************************** + * Name: esp_queue_recv + * + * Description: + * Receive message from queue within a certain period of time + * + * Input Parameters: + * queue - Message queue data pointer + * item - Message data pointer + * ticks - Wait ticks + * + * Returned Value: + * True if success or false if fail + * + ****************************************************************************/ + +static int32_t esp_queue_recv(void *queue, void *item, uint32_t ticks) +{ + ssize_t ret; + struct timespec timeout; + unsigned int prio; + struct mq_adpt *mq_adpt = (struct mq_adpt *)queue; + + if (ticks == OSI_FUNCS_TIME_BLOCKING) + { + ret = file_mq_receive(&mq_adpt->mq, (char *)item, + mq_adpt->msgsize, &prio); + if (ret < 0) + { + wlerr("Failed to receive from mqueue error=%d\n", ret); + } + } + else + { + ret = clock_gettime(CLOCK_REALTIME, &timeout); + if (ret < 0) + { + wlerr("Failed to get time\n"); + return false; + } + + if (ticks) + { + esp_update_time(&timeout, ticks); + } + + ret = file_mq_timedreceive(&mq_adpt->mq, (char *)item, + mq_adpt->msgsize, &prio, &timeout); + if (ret < 0) + { + wlerr("Failed to timedreceive from mqueue error=%d\n", + ret); + } + } + + return ret > 0 ? true : false; +} + +/**************************************************************************** + * Name: esp_queue_msg_waiting + * + * Description: + * Get message number in the message queue + * + * Input Parameters: + * queue - Message queue data pointer + * + * Returned Value: + * Message number + * + ****************************************************************************/ + +static uint32_t esp_queue_msg_waiting(void *queue) +{ + int ret; + struct mq_attr attr; + struct mq_adpt *mq_adpt = (struct mq_adpt *)queue; + + ret = file_mq_getattr(&mq_adpt->mq, &attr); + if (ret < 0) + { + wlerr("Failed to get attr from mqueue error=%d\n", ret); + return 0; + } + + return attr.mq_curmsgs; +} + +/**************************************************************************** + * Name: esp_event_group_create + * + * Description: + * Don't support + * + ****************************************************************************/ + +static void *esp_event_group_create(void) +{ + DEBUGPANIC(); + + return NULL; +} + +/**************************************************************************** + * Name: esp_event_group_delete + * + * Description: + * Don't support + * + ****************************************************************************/ + +static void esp_event_group_delete(void *event) +{ + DEBUGPANIC(); +} + +/**************************************************************************** + * Name: esp_event_group_set_bits + * + * Description: + * Don't support + * + ****************************************************************************/ + +static uint32_t esp_event_group_set_bits(void *event, uint32_t bits) +{ + DEBUGPANIC(); + + return false; +} + +/**************************************************************************** + * Name: esp_event_group_clear_bits + * + * Description: + * Don't support + * + ****************************************************************************/ + +static uint32_t esp_event_group_clear_bits(void *event, uint32_t bits) +{ + DEBUGPANIC(); + + return false; +} + +/**************************************************************************** + * Name: esp_event_group_wait_bits + * + * Description: + * Don't support + * + ****************************************************************************/ + +static uint32_t esp_event_group_wait_bits(void *event, + uint32_t bits_to_wait_for, + int32_t clear_on_exit, + int32_t wait_for_all_bits, + uint32_t block_time_tick) +{ + DEBUGPANIC(); + + return false; +} + +/**************************************************************************** + * Name: esp_task_create_pinned_to_core + * + * Description: + * Create task and bind it to target CPU, the task will run when it + * is created + * + * Input Parameters: + * entry - Task entry + * name - Task name + * stack_depth - Task stack size + * param - Task private data + * prio - Task priority + * task_handle - Task handle pointer which is used to pause, resume + * and delete the task + * core_id - CPU which the task runs in + * + * Returned Value: + * True if success or false if fail + * + ****************************************************************************/ + +static int32_t esp_task_create_pinned_to_core(void *entry, + const char *name, + uint32_t stack_depth, + void *param, + uint32_t prio, + void *task_handle, + uint32_t core_id) +{ + int pid; +#ifdef CONFIG_SMP + int ret; + cpu_set_t cpuset; +#endif + uint32_t target_prio = prio; + + if (target_prio < ESP_MAX_PRIORITIES) + { + target_prio += esp_task_get_max_priority() - ESP_MAX_PRIORITIES; + } + + pid = kthread_create(name, target_prio, stack_depth, entry, + (char * const *)param); + if (pid > 0) + { + if (task_handle != NULL) + { + *((int *)task_handle) = pid; + } +#ifdef CONFIG_SMP + if (core_id < CONFIG_SMP_NCPUS) + { + CPU_ZERO(&cpuset); + CPU_SET(core_id, &cpuset); + ret = nxsched_set_affinity(pid, sizeof(cpuset), &cpuset); + if (ret) + { + wlerr("Failed to set affinity error=%d\n", ret); + return false; + } + } +#endif + } + else + { + wlerr("Failed to create task\n"); + } + + return pid > 0; +} + +/**************************************************************************** + * Name: esp_task_create + * + * Description: + * Create task and the task will run when it is created + * + * Input Parameters: + * entry - Task entry + * name - Task name + * stack_depth - Task stack size + * param - Task private data + * prio - Task priority + * task_handle - Task handle pointer which is used to pause, resume + * and delete the task + * + * Returned Value: + * True if success or false if fail + * + ****************************************************************************/ + +static int32_t esp_task_create(void *entry, const char *name, + uint32_t stack_depth, void *param, + uint32_t prio, void *task_handle) +{ + return esp_task_create_pinned_to_core(entry, name, stack_depth, param, + prio, task_handle, UINT32_MAX); +} + +/**************************************************************************** + * Name: esp_task_delete + * + * Description: + * Delete the target task + * + * Input Parameters: + * task_handle - Task handle pointer which is used to pause, resume + * and delete the task + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp_task_delete(void *task_handle) +{ + pid_t pid = (pid_t)((uintptr_t)task_handle); + + kthread_delete(pid); +} + +/**************************************************************************** + * Name: esp_task_delay + * + * Description: + * Current task wait for some ticks + * + * Input Parameters: + * tick - Waiting ticks + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp_task_delay(uint32_t tick) +{ + useconds_t us = TICK2USEC(tick); + + nxsig_usleep(us); +} + +/**************************************************************************** + * Name: esp_task_ms_to_tick + * + * Description: + * Transform from millim seconds to system ticks + * + * Input Parameters: + * ms - Millim seconds + * + * Returned Value: + * System ticks + * + ****************************************************************************/ + +static int32_t esp_task_ms_to_tick(uint32_t ms) +{ + return MSEC2TICK(ms); +} + +/**************************************************************************** + * Name: esp_task_get_current_task + * + * Description: + * Transform from millim seconds to system ticks + * + * Input Parameters: + * ms - Millim seconds + * + * Returned Value: + * System ticks + * + ****************************************************************************/ + +static void *esp_task_get_current_task(void) +{ + pid_t pid = nxsched_gettid(); + + return (void *)((uintptr_t)pid); +} + +/**************************************************************************** + * Name: esp_task_get_max_priority + * + * Description: + * Get OS task maximum priority + * + * Input Parameters: + * None + * + * Returned Value: + * Task maximum priority + * + ****************************************************************************/ + +static int32_t esp_task_get_max_priority(void) +{ + return SCHED_PRIORITY_MAX; +} + +/**************************************************************************** + * Name: esp_malloc + * + * Description: + * Allocate a block of memory + * + * Input Parameters: + * size - memory size + * + * Returned Value: + * Memory pointer + * + ****************************************************************************/ + +static void *esp_malloc(uint32_t size) +{ + return kmm_malloc(size); +} + +/**************************************************************************** + * Name: esp_free + * + * Description: + * Free a block of memory + * + * Input Parameters: + * ptr - memory block + * + * Returned Value: + * No + * + ****************************************************************************/ + +static void esp_free(void *ptr) +{ +#ifdef CONFIG_XTENSA_IMEM_USE_SEPARATE_HEAP + if (xtensa_imm_heapmember(ptr)) + { + xtensa_imm_free(ptr); + } + else +#endif +#ifdef CONFIG_MM_KERNEL_HEAP + if (kmm_heapmember(ptr)) +#endif + { + kmm_free(ptr); + } +#ifdef CONFIG_MM_KERNEL_HEAP + else + { + free(ptr); + } +#endif +} + +/**************************************************************************** + * Name: esp_event_id_map + * + * Description: + * Transform from esp-idf event ID to Wi-Fi adapter event ID + * + * Input Parameters: + * event_id - esp-idf event ID + * + * Returned Value: + * Wi-Fi adapter event ID + * + ****************************************************************************/ + +static int esp_event_id_map(int event_id) +{ + int id; + + switch (event_id) + { + case WIFI_EVENT_SCAN_DONE: + id = WIFI_ADPT_EVT_SCAN_DONE; + break; + +#ifdef ESPRESSIF_WLAN_HAS_STA + case WIFI_EVENT_STA_START: + id = WIFI_ADPT_EVT_STA_START; + break; + + case WIFI_EVENT_STA_CONNECTED: + id = WIFI_ADPT_EVT_STA_CONNECT; + break; + + case WIFI_EVENT_STA_DISCONNECTED: + id = WIFI_ADPT_EVT_STA_DISCONNECT; + break; + + case WIFI_EVENT_STA_AUTHMODE_CHANGE: + id = WIFI_ADPT_EVT_STA_AUTHMODE_CHANGE; + break; + + case WIFI_EVENT_STA_STOP: + id = WIFI_ADPT_EVT_STA_STOP; + break; +#endif /* ESPRESSIF_WLAN_HAS_STA */ + +#ifdef ESPRESSIF_WLAN_HAS_SOFTAP + case WIFI_EVENT_AP_START: + id = WIFI_ADPT_EVT_AP_START; + break; + + case WIFI_EVENT_AP_STOP: + id = WIFI_ADPT_EVT_AP_STOP; + break; + + case WIFI_EVENT_AP_STACONNECTED: + id = WIFI_ADPT_EVT_AP_STACONNECTED; + break; + + case WIFI_EVENT_AP_STADISCONNECTED: + id = WIFI_ADPT_EVT_AP_STADISCONNECTED; + break; +#endif /* ESPRESSIF_WLAN_HAS_SOFTAP */ + + default: + return -1; + } + + return id; +} + +/**************************************************************************** + * Name: esp_evt_work_cb + * + * Description: + * Process the cached event + * + * Input Parameters: + * arg - No mean + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp_evt_work_cb(void *arg) +{ + int ret; + irqstate_t flags; + struct evt_adpt *evt_adpt; + struct wifi_notify *notify; + wifi_ps_type_t ps_type = DEFAULT_PS_MODE; + + while (1) + { + flags = spin_lock_irqsave(&g_lock); + evt_adpt = (struct evt_adpt *)sq_remfirst(&g_wifi_evt_queue); + spin_unlock_irqrestore(&g_lock, flags); + if (!evt_adpt) + { + break; + } + + esp_wifi_lock(true); + + switch (evt_adpt->id) + { + case WIFI_ADPT_EVT_SCAN_DONE: + esp_wifi_scan_event_parse(); + break; + +#ifdef ESPRESSIF_WLAN_HAS_STA + case WIFI_ADPT_EVT_STA_START: + wlinfo("Wi-Fi sta start\n"); + + g_sta_connected = false; + ret = esp_wifi_set_ps(ps_type); + + if (ret) + { + wlerr("Failed to set power save type\n"); + break; + } + else + { + wlinfo("INFO: Set ps type=%d\n", ps_type); + } + + ret = esp_wifi_get_config(WIFI_IF_STA, &g_sta_wifi_cfg); + if (ret) + { + wlerr("Failed to get Wi-Fi config data ret=%d\n", ret); + } + break; + + case WIFI_ADPT_EVT_STA_CONNECT: + wlinfo("Wi-Fi sta connect\n"); + g_sta_connected = true; + ret = esp_wlan_sta_set_linkstatus(true); + if (ret < 0) + { + wlerr("ERROR: Failed to set Wi-Fi station link status\n"); + } + + break; + + case WIFI_ADPT_EVT_STA_DISCONNECT: + wlinfo("Wi-Fi sta disconnect\n"); + g_sta_connected = false; + ret = esp_wlan_sta_set_linkstatus(false); + if (ret < 0) + { + wlerr("ERROR: Failed to set Wi-Fi station link status\n"); + } + + if (g_sta_reconnect) + { + ret = esp_wifi_connect(); + if (ret) + { + wlerr("Failed to connect AP error=%d\n", ret); + } + } + break; + + case WIFI_ADPT_EVT_STA_STOP: + wlinfo("Wi-Fi sta stop\n"); + g_sta_connected = false; + break; +#endif /* ESPRESSIF_WLAN_HAS_STA */ + +#ifdef ESPRESSIF_WLAN_HAS_SOFTAP + case WIFI_ADPT_EVT_AP_START: + wlinfo("INFO: Wi-Fi softap start\n"); + + ret = esp_wifi_set_ps(ps_type); + + if (ret) + { + wlerr("Failed to set power save type\n"); + break; + } + else + { + wlinfo("INFO: Set ps type=%d\n", ps_type); + } + + ret = esp_wifi_get_config(WIFI_IF_AP, &g_softap_wifi_cfg); + if (ret) + { + wlerr("Failed to get Wi-Fi config data ret=%d\n", ret); + } + break; + + case WIFI_ADPT_EVT_AP_STOP: + wlinfo("INFO: Wi-Fi softap stop\n"); + break; + + case WIFI_ADPT_EVT_AP_STACONNECTED: + wlinfo("INFO: Wi-Fi station join\n"); + break; + + case WIFI_ADPT_EVT_AP_STADISCONNECTED: + wlinfo("INFO: Wi-Fi station leave\n"); + break; +#endif /* ESPRESSIF_WLAN_HAS_SOFTAP */ + default: + break; + } + + notify = &g_wifi_notify[evt_adpt->id]; + if (notify->assigned) + { + notify->event.sigev_value.sival_ptr = evt_adpt->buf; + + ret = nxsig_notification(notify->pid, ¬ify->event, + SI_QUEUE, ¬ify->work); + if (ret < 0) + { + wlwarn("nxsig_notification event ID=%d failed: %d\n", + evt_adpt->id, ret); + } + } + + esp_wifi_lock(false); + + kmm_free(evt_adpt); + } +} + +/**************************************************************************** + * Name: wifi_env_is_chip + * + * Description: + * Config chip environment + * + * Returned Value: + * True if on chip or false if on FPGA. + * + ****************************************************************************/ + +static bool wifi_env_is_chip(void) +{ + return true; +} + +/**************************************************************************** + * Name: wifi_set_intr + * + * Description: + * Do nothing + * + * Input Parameters: + * cpu_no - The CPU which the interrupt number belongs. + * intr_source - The interrupt hardware source number. + * intr_num - The interrupt number CPU. + * intr_prio - The interrupt priority. + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void wifi_set_intr(int32_t cpu_no, uint32_t intr_source, + uint32_t intr_num, int32_t intr_prio) +{ + wlinfo("cpu_no=%" PRId32 ", intr_source=%" PRIu32 + ", intr_num=%" PRIu32 ", intr_prio=%" PRId32 "\n", + cpu_no, intr_source, intr_num, intr_prio); +} + +/**************************************************************************** + * Name: wifi_clear_intr + * + * Description: + * Don't support + * + ****************************************************************************/ + +static void IRAM_ATTR wifi_clear_intr(uint32_t intr_source, + uint32_t intr_num) +{ +} + +/**************************************************************************** + * Name: esp_event_post + * + * Description: + * Active work queue and let the work to process the cached event + * + * Input Parameters: + * event_base - Event set name + * event_id - Event ID + * event_data - Event private data + * event_data_size - Event data size + * ticks - Waiting system ticks + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int32_t esp_event_post(esp_event_base_t event_base, + int32_t event_id, + void *event_data, + size_t event_data_size, + uint32_t ticks) +{ + size_t size; + int32_t id; + irqstate_t flags; + struct evt_adpt *evt_adpt; + + wlinfo("Event: base=%s id=%d data=%p data_size=%d ticks=%u\n", event_base, + event_id, event_data, event_data_size, ticks); + + id = esp_event_id_map(event_id); + if (id < 0) + { + wlinfo("No process event %d\n", event_id); + return -1; + } + + size = event_data_size + sizeof(struct evt_adpt); + evt_adpt = kmm_malloc(size); + if (!evt_adpt) + { + wlerr("Failed to alloc %d memory\n", size); + return -1; + } + + evt_adpt->id = id; + memcpy(evt_adpt->buf, event_data, event_data_size); + + flags = spin_lock_irqsave(&g_lock); + sq_addlast(&evt_adpt->entry, &g_wifi_evt_queue); + spin_unlock_irqrestore(&g_lock, flags); + + work_queue(LPWORK, &g_wifi_evt_work, esp_evt_work_cb, NULL, 0); + + return 0; +} + +/**************************************************************************** + * Name: esp_get_free_heap_size + * + * Description: + * Get free heap size by byte + * + * Input Parameters: + * None + * + * Returned Value: + * Free heap size + * + ****************************************************************************/ + +static uint32_t esp_get_free_heap_size(void) +{ + struct mallinfo info; + + info = kmm_mallinfo(); + return info.fordblks; +} + +/**************************************************************************** + * Name: wifi_apb80m_request + * + * Description: + * Take Wi-Fi lock in auto-sleep + * + ****************************************************************************/ + +static void wifi_apb80m_request(void) +{ +#ifdef CONFIG_ESP32S2_AUTO_SLEEP + esp32s2_pm_lockacquire(); +#endif +} + +/**************************************************************************** + * Name: wifi_apb80m_release + * + * Description: + * Release Wi-Fi lock in auto-sleep + * + ****************************************************************************/ + +static void wifi_apb80m_release(void) +{ +#ifdef CONFIG_ESP32S2_AUTO_SLEEP + esp32s2_pm_lockrelease(); +#endif +} + +/**************************************************************************** + * Name: esp_empty_wrapper + * + * Description: + * This is a wrapper for unused functions in ESP WiFi compatibility. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void IRAM_ATTR esp_empty_wrapper(void) +{ +} + +/**************************************************************************** + * Name: esp_phy_enable_wrapper + * + * Description: + * This is a wrapper for enabling the ESP PHY. It calls the esp_phy_enable + * function with PHY_MODEM_WIFI as the argument. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp_phy_enable_wrapper(void) +{ + esp_phy_enable(PHY_MODEM_WIFI); +} + +/**************************************************************************** + * Name: esp_phy_disable_wrapper + * + * Description: + * This is a wrapper for disabling the ESP PHY. It first calls the + * phy_wifi_enable_set function with 0 as the argument. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp_phy_disable_wrapper(void) +{ + esp_phy_disable(PHY_MODEM_WIFI); +} + +/**************************************************************************** + * Name: esp_wifi_read_mac + * + * Description: + * Read MAC address from efuse + * + * Input Parameters: + * mac - MAC address buffer pointer + * type - MAC address type + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +static int32_t esp_wifi_read_mac(uint8_t *mac, uint32_t type) +{ + return esp_read_mac(mac, type); +} + +/**************************************************************************** + * Name: esp_timer_arm + * + * Description: + * Set timer timeout period and repeat flag + * + * Input Parameters: + * ptimer - timer data pointer + * ms - millim seconds + * repeat - true: run cycle, false: run once + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp_timer_arm(void *ptimer, uint32_t ms, bool repeat) +{ + esp_timer_arm_us(ptimer, ms * 1000, repeat); +} + +/**************************************************************************** + * Name: esp_timer_disarm + * + * Description: + * Disable timer + * + * Input Parameters: + * ptimer - timer data pointer + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp_timer_disarm(void *ptimer) +{ + struct ets_timer *ets_timer = (struct ets_timer *)ptimer; + esp_timer_handle_t esp_timer = (esp_timer_handle_t)ets_timer->timer_arg; + + if (ets_timer->timer_expire == TIMER_INITIALIZED_VAL) + { + esp_timer_stop(esp_timer); + } +} + +/**************************************************************************** + * Name: esp32s2_timer_done + * + * Description: + * Disable and free timer + * + * Input Parameters: + * ptimer - timer data pointer + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp32s2_timer_done(void *ptimer) +{ + struct ets_timer *ets_timer = (struct ets_timer *)ptimer; + esp_timer_handle_t esp_timer = (esp_timer_handle_t)ets_timer->timer_arg; + + if (ets_timer->timer_expire == TIMER_INITIALIZED_VAL) + { + ets_timer->timer_expire = 0; + esp_timer_delete(esp_timer); + ets_timer->timer_arg = NULL; + } +} + +/**************************************************************************** + * Name: esp_timer_setfn + * + * Description: + * Set timer callback function and private data + * + * Input Parameters: + * ptimer - Timer data pointer + * pfunction - Callback function + * parg - Callback function private data + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp_timer_setfn(void *ptimer, void *pfunction, void *parg) +{ + int ret; + esp_timer_handle_t esp_timer; + struct ets_timer *ets_timer = (struct ets_timer *)ptimer; + + if (ets_timer->timer_expire != TIMER_INITIALIZED_VAL) + { + ets_timer->timer_arg = NULL; + } + + if (ets_timer->timer_arg == NULL) + { + const esp_timer_create_args_t create_args = + { + .callback = pfunction, + .arg = parg, + .name = "ETSTimer", + .dispatch_method = ESP_TIMER_TASK + }; + + ret = esp_timer_create(&create_args, &esp_timer); + if (ret) + { + wlerr("Failed to create ets_timer error=%d\n", ret); + } + else + { + ets_timer->timer_arg = esp_timer; + ets_timer->timer_expire = TIMER_INITIALIZED_VAL; + } + } +} + +/**************************************************************************** + * Name: esp_timer_arm_us + * + * Description: + * Set timer timeout period and repeat flag + * + * Input Parameters: + * ptimer - timer data pointer + * us - micro seconds + * repeat - true: run cycle, false: run once + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp_timer_arm_us(void *ptimer, uint32_t us, bool repeat) +{ + int ret; + struct ets_timer *ets_timer = (struct ets_timer *)ptimer; + esp_timer_handle_t esp_timer = (esp_timer_handle_t)ets_timer->timer_arg; + + if (ets_timer->timer_expire == TIMER_INITIALIZED_VAL) + { + esp_timer_stop(esp_timer); + if (!repeat) + { + ret = esp_timer_start_once(esp_timer, us); + } + else + { + ret = esp_timer_start_periodic(esp_timer, us); + } + + if (ret) + { + wlerr("Fail to start %s timer error%d\n", + repeat ? "periodic" : "once", + ret); + } + } +} + +/**************************************************************************** + * Name: wifi_reset_mac + * + * Description: + * Reset Wi-Fi hardware MAC + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void wifi_reset_mac(void) +{ + periph_module_reset(PERIPH_WIFI_MODULE); +} + +/**************************************************************************** + * Name: wifi_clock_enable + * + * Description: + * Enable Wi-Fi clock + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void wifi_clock_enable(void) +{ + wifi_module_enable(); +} + +/**************************************************************************** + * Name: wifi_clock_disable + * + * Description: + * Disable Wi-Fi clock + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void wifi_clock_disable(void) +{ + wifi_module_disable(); +} + +/**************************************************************************** + * Name: esp32s2_timer_get_time + * + * Description: + * Get system time of type int64_t + * + * Input Parameters: + * periph - No mean + * + * Returned Value: + * System time + * + ****************************************************************************/ + +int64_t esp32s2_timer_get_time(void) +{ + return (int64_t)rt_timer_time_us(); +} + +/**************************************************************************** + * Name: esp_nvs_set_i8 + * + * Description: + * Save data of type int8_t into file system + * + * Input Parameters: + * handle - NVS handle + * key - Data index + * value - Stored data + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +static int32_t esp_nvs_set_i8(uint32_t handle, + const char *key, + int8_t value) +{ + DEBUGPANIC(); + + return -1; +} + +/**************************************************************************** + * Name: esp_nvs_get_i8 + * + * Description: + * Read data of type int8_t from file system + * + * Input Parameters: + * handle - NVS handle + * key - Data index + * out_value - Read buffer pointer + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +static int32_t esp_nvs_get_i8(uint32_t handle, + const char *key, + int8_t *out_value) +{ + DEBUGPANIC(); + + return -1; +} + +/**************************************************************************** + * Name: esp_nvs_set_u8 + * + * Description: + * Save data of type uint8_t into file system + * + * Input Parameters: + * handle - NVS handle + * key - Data index + * value - Stored data + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +static int32_t esp_nvs_set_u8(uint32_t handle, + const char *key, + uint8_t value) +{ + DEBUGPANIC(); + + return -1; +} + +/**************************************************************************** + * Name: esp_nvs_get_u8 + * + * Description: + * Read data of type uint8_t from file system + * + * Input Parameters: + * handle - NVS handle + * key - Data index + * out_value - Read buffer pointer + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +static int32_t esp_nvs_get_u8(uint32_t handle, + const char *key, + uint8_t *out_value) +{ + DEBUGPANIC(); + + return -1; +} + +/**************************************************************************** + * Name: esp_nvs_set_u16 + * + * Description: + * Save data of type uint16_t into file system + * + * Input Parameters: + * handle - NVS handle + * key - Data index + * value - Stored data + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +static int32_t esp_nvs_set_u16(uint32_t handle, + const char *key, + uint16_t value) +{ + DEBUGPANIC(); + + return -1; +} + +/**************************************************************************** + * Name: esp_nvs_get_u16 + * + * Description: + * Read data of type uint16_t from file system + * + * Input Parameters: + * handle - NVS handle + * key - Data index + * out_value - Read buffer pointer + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +static int32_t esp_nvs_get_u16(uint32_t handle, + const char *key, + uint16_t *out_value) +{ + DEBUGPANIC(); + + return -1; +} + +/**************************************************************************** + * Name: esp_nvs_open + * + * Description: + * Create a file system storage data object + * + * Input Parameters: + * name - Storage index + * open_mode - Storage mode + * out_handle - Storage handle + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +static int32_t esp_nvs_open(const char *name, + uint32_t open_mode, + uint32_t *out_handle) +{ + DEBUGPANIC(); + + return -1; +} + +/**************************************************************************** + * Name: esp_nvs_close + * + * Description: + * Close storage data object and free resource + * + * Input Parameters: + * handle - NVS handle + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +static void esp_nvs_close(uint32_t handle) +{ + DEBUGPANIC(); +} + +/**************************************************************************** + * Name: esp_nvs_commit + * + * Description: + * This function has no practical effect + * + ****************************************************************************/ + +static int32_t esp_nvs_commit(uint32_t handle) +{ + return 0; +} + +/**************************************************************************** + * Name: esp_nvs_set_blob + * + * Description: + * Save a block of data into file system + * + * Input Parameters: + * handle - NVS handle + * key - Data index + * value - Stored buffer pointer + * length - Buffer length + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +static int32_t esp_nvs_set_blob(uint32_t handle, + const char *key, + const void *value, + size_t length) +{ + DEBUGPANIC(); + + return -1; +} + +/**************************************************************************** + * Name: esp_nvs_get_blob + * + * Description: + * Read a block of data from file system + * + * Input Parameters: + * handle - NVS handle + * key - Data index + * out_value - Read buffer pointer + * length - Buffer length + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +static int32_t esp_nvs_get_blob(uint32_t handle, + const char *key, + void *out_value, + size_t *length) +{ + DEBUGPANIC(); + + return -1; +} + +/**************************************************************************** + * Name: esp_nvs_erase_key + * + * Description: + * Read a block of data from file system + * + * Input Parameters: + * handle - NVS handle + * key - Data index + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +static int32_t esp_nvs_erase_key(uint32_t handle, const char *key) +{ + DEBUGPANIC(); + + return -1; +} + +/**************************************************************************** + * Name: esp_get_random + * + * Description: + * Fill random data int given buffer of given length + * + * Input Parameters: + * buf - buffer pointer + * len - buffer length + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +static int32_t esp_get_random(uint8_t *buf, size_t len) +{ + esp_fill_random(buf, len); + + return 0; +} + +/**************************************************************************** + * Name: esp_get_time + * + * Description: + * Get std C time + * + * Input Parameters: + * t - buffer to store time of type timeval + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +static int32_t esp_get_time(void *t) +{ + int ret; + struct timeval tv; + struct time_adpt *time_adpt = (struct time_adpt *)t; + + ret = gettimeofday(&tv, NULL); + if (!ret) + { + time_adpt->sec = (time_t)tv.tv_sec; + time_adpt->usec = (suseconds_t)tv.tv_usec; + } + else + { + wlerr("Failed to get time of day\n"); + } + + return ret; +} + +/**************************************************************************** + * Name: esp_rand + * + * Description: + * Get random data of type uint32_t + * + * Input Parameters: + * None + * + * Returned Value: + * Random data + * + ****************************************************************************/ + +static uint32_t esp_rand(void) +{ + return esp_random(); +} + +/**************************************************************************** + * Name: esp_clk_slowclk_cal_get_wrapper + * + * Description: + * Get the calibration value of RTC slow clock + * + * Input Parameters: + * None + * + * Returned Value: + * The calibration value obtained using rtc_clk_cal + * + ****************************************************************************/ + +static uint32_t esp_clk_slowclk_cal_get_wrapper(void) +{ + /* The bit width of WiFi light sleep clock calibration is 12 while the one + * of the system is 19. It should shift 19 - 12 = 7. + */ + + if (REG_GET_FIELD(SYSTEM_BT_LPCK_DIV_FRAC_REG, SYSTEM_LPCLK_SEL_XTAL)) + { + uint64_t time_per_us = 1000000ULL; + return (((time_per_us << RTC_CLK_CAL_FRACT) / (MHZ)) >> + (RTC_CLK_CAL_FRACT - SOC_WIFI_LIGHT_SLEEP_CLK_WIDTH)); + } + else + { + return (getreg32(RTC_SLOW_CLK_CAL_REG) >> + (RTC_CLK_CAL_FRACT - SOC_WIFI_LIGHT_SLEEP_CLK_WIDTH)); + } +} + +/**************************************************************************** + * Name: esp_log_writev_wrapper + * + * Description: + * Output log with by format string and its arguments + * + * Input Parameters: + * level - log level, no mean here + * tag - log TAG, no mean here + * format - format string + * args - arguments list + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp_log_writev_wrapper(uint32_t level, const char *tag, + const char *format, va_list args) +{ + esp_log_level_t max_level; + +#if defined (CONFIG_DEBUG_WIRELESS_INFO) + max_level = ESP_LOG_VERBOSE; +#elif defined (CONFIG_DEBUG_WIRELESS_WARN) + max_level = ESP_LOG_WARN; +#elif defined (CONFIG_DEBUG_WIRELESS_ERROR) + max_level = ESP_LOG_ERROR; +#else + max_level = ESP_LOG_NONE; +#endif + + if (level <= max_level) + { + esp_log_writev(level, tag, format, args); + } +} + +/**************************************************************************** + * Name: esp_log_write_wrapper + * + * Description: + * Output log with by format string and its arguments + * + * Input Parameters: + * level - log level, no mean here + * tag - log TAG, no mean here + * format - format string + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp_log_write_wrapper(uint32_t level, + const char *tag, + const char *format, ...) +{ + esp_log_level_t max_level; + +#if defined (CONFIG_DEBUG_WIRELESS_INFO) + max_level = ESP_LOG_VERBOSE; +#elif defined (CONFIG_DEBUG_WIRELESS_WARN) + max_level = ESP_LOG_WARN; +#elif defined (CONFIG_DEBUG_WIRELESS_ERROR) + max_level = ESP_LOG_ERROR; +#else + max_level = ESP_LOG_NONE; +#endif + + if (level <= max_level) + { + va_list list; + va_start(list, format); + esp_log_writev(level, tag, format, list); + va_end(list); + } +} + +/**************************************************************************** + * Name: esp_malloc_internal + * + * Description: + * Drivers allocate a block of memory + * + * Input Parameters: + * size - memory size + * + * Returned Value: + * Memory pointer + * + ****************************************************************************/ + +static void *esp_malloc_internal(size_t size) +{ +#ifdef CONFIG_MM_KERNEL_HEAP + return kmm_malloc(size); +#elif defined(CONFIG_XTENSA_IMEM_USE_SEPARATE_HEAP) + return xtensa_imm_malloc(size); +#else + void *ptr = kmm_malloc(size); + + if (ptr != NULL) + { + if (esp32s2_ptr_extram(ptr)) + { + kmm_free(ptr); + return NULL; + } + } + + return ptr; +#endif +} + +/**************************************************************************** + * Name: esp_realloc_internal + * + * Description: + * Drivers allocate a block of memory by old memory block + * + * Input Parameters: + * ptr - old memory pointer + * size - memory size + * + * Returned Value: + * New memory pointer + * + ****************************************************************************/ + +static void *esp_realloc_internal(void *ptr, size_t size) +{ +#ifdef CONFIG_MM_KERNEL_HEAP + return kmm_realloc(ptr, size); +#elif defined(CONFIG_XTENSA_IMEM_USE_SEPARATE_HEAP) + return xtensa_imm_realloc(ptr, size); +#else + void *old_ptr = ptr; + void *new_ptr = NULL; + size_t old_size = 0; + if (size == 0) + { + kmm_free(ptr); + return NULL; + } + + new_ptr = kmm_malloc(size); + if (new_ptr != NULL) + { + if (esp32s2_ptr_extram(new_ptr)) + { + kmm_free(new_ptr); + return NULL; + } + + old_size = kmm_malloc_size(old_ptr); + DEBUGASSERT(old_size > 0); + memcpy(new_ptr, old_ptr, MIN(old_size, size)); + kmm_free(old_ptr); + return new_ptr; + } + + return NULL; +#endif +} + +/**************************************************************************** + * Name: esp_calloc_internal + * + * Description: + * Drivers allocate some continuous blocks of memory + * + * Input Parameters: + * n - memory block number + * size - memory block size + * + * Returned Value: + * New memory pointer + * + ****************************************************************************/ + +static void *esp_calloc_internal(size_t n, size_t size) +{ +#ifdef CONFIG_MM_KERNEL_HEAP + return kmm_calloc(n, size); +#elif defined(CONFIG_XTENSA_IMEM_USE_SEPARATE_HEAP) + return xtensa_imm_calloc(n, size); +#else + void *ptr = kmm_calloc(n, size); + if (ptr != NULL) + { + if (esp32s2_ptr_extram(ptr)) + { + kmm_free(ptr); + return NULL; + } + } + + return ptr; +#endif +} + +/**************************************************************************** + * Name: esp_zalloc_internal + * + * Description: + * Drivers allocate a block of memory and clear it with 0 + * + * Input Parameters: + * size - memory size + * + * Returned Value: + * New memory pointer + * + ****************************************************************************/ + +static void *esp_zalloc_internal(size_t size) +{ +#ifdef CONFIG_MM_KERNEL_HEAP + return kmm_zalloc(size); +#elif defined(CONFIG_XTENSA_IMEM_USE_SEPARATE_HEAP) + return xtensa_imm_zalloc(size); +#else + void *ptr = kmm_zalloc(size); + if (ptr != NULL) + { + if (esp32s2_ptr_extram(ptr)) + { + kmm_free(ptr); + return NULL; + } + } + + return ptr; +#endif +} + +/**************************************************************************** + * Name: esp_wifi_malloc + * + * Description: + * Applications allocate a block of memory + * + * Input Parameters: + * size - memory size + * + * Returned Value: + * Memory pointer + * + ****************************************************************************/ + +static void *esp_wifi_malloc(size_t size) +{ + return kmm_malloc(size); +} + +/**************************************************************************** + * Name: esp_wifi_realloc + * + * Description: + * Applications allocate a block of memory by old memory block + * + * Input Parameters: + * ptr - old memory pointer + * size - memory size + * + * Returned Value: + * New memory pointer + * + ****************************************************************************/ + +static void *esp_wifi_realloc(void *ptr, size_t size) +{ + return kmm_realloc(ptr, size); +} + +/**************************************************************************** + * Name: esp_wifi_calloc + * + * Description: + * Applications allocate some continuous blocks of memory + * + * Input Parameters: + * n - memory block number + * size - memory block size + * + * Returned Value: + * New memory pointer + * + ****************************************************************************/ + +static void *esp_wifi_calloc(size_t n, size_t size) +{ + return kmm_calloc(n, size); +} + +/**************************************************************************** + * Name: esp_wifi_zalloc + * + * Description: + * Applications allocate a block of memory and clear it with 0 + * + * Input Parameters: + * size - memory size + * + * Returned Value: + * New memory pointer + * + ****************************************************************************/ + +static void *esp_wifi_zalloc(size_t size) +{ + return kmm_zalloc(size); +} + +/**************************************************************************** + * Name: esp_wifi_create_queue + * + * Description: + * Create Wi-Fi static message queue + * + * Input Parameters: + * queue_len - queue message number + * item_size - message size + * + * Returned Value: + * Wi-Fi static message queue data pointer + * + ****************************************************************************/ + +static void *esp_wifi_create_queue(int32_t queue_len, int32_t item_size) +{ + wifi_static_queue_t *wifi_queue; + + wifi_queue = kmm_malloc(sizeof(wifi_static_queue_t)); + if (!wifi_queue) + { + wlerr("Failed to kmm_malloc\n"); + return NULL; + } + + wifi_queue->handle = esp_queue_create(queue_len, item_size); + if (!wifi_queue->handle) + { + wlerr("Failed to create queue\n"); + kmm_free(wifi_queue); + return NULL; + } + + return wifi_queue; +} + +/**************************************************************************** + * Name: esp_wifi_delete_queue + * + * Description: + * Delete Wi-Fi static message queue + * + * Input Parameters: + * queue - Wi-Fi static message queue data pointer + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp_wifi_delete_queue(void *queue) +{ + wifi_static_queue_t *wifi_queue = (wifi_static_queue_t *)queue; + + esp_queue_delete(wifi_queue->handle); + kmm_free(wifi_queue); +} + +/**************************************************************************** + * Name: coex_init_wrapper + * + * Description: + * Init software coexist + * + * Input Parameters: + * none + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned + * on failure. + * + ****************************************************************************/ + +static int coex_init_wrapper(void) +{ + return 0; +} + +/**************************************************************************** + * Name: coex_deinit_wrapper + * + * Description: + * De-init software coexist + * + * Input Parameters: + * none + * + * Returned Value: + * none + * + ****************************************************************************/ + +static void coex_deinit_wrapper(void) +{ +} + +/**************************************************************************** + * Name: coex_enable_wrapper + * + * Description: + * Enable software coexist + * + * Input Parameters: + * none + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned + * on failure. + * + ****************************************************************************/ + +static int coex_enable_wrapper(void) +{ + return 0; +} + +/**************************************************************************** + * Name: coex_disable_wrapper + * + * Description: + * Disable software coexist + * + * Input Parameters: + * none + * + * Returned Value: + * none + * + ****************************************************************************/ + +static void coex_disable_wrapper(void) +{ +} + +/**************************************************************************** + * Name: coex_status_get_wrapper + * + * Description: + * Get software coexist status. + * + * Input Parameters: + * none + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned + * on failure. + * + ****************************************************************************/ + +static IRAM_ATTR uint32_t coex_status_get_wrapper(void) +{ + return 0; +} + +/**************************************************************************** + * Name: coex_wifi_request_wrapper + * + * Description: + * Request Wi-Fi coexistence. + * + * Input Parameters: + * event - WiFi event + * latency - WiFi will request coexistence after latency + * duration - duration for WiFi to request coexistence + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned + * on failure. + * + ****************************************************************************/ + +static int32_t coex_wifi_request_wrapper(uint32_t event, uint32_t latency, + uint32_t duration) +{ + return 0; +} + +/**************************************************************************** + * Name: coex_wifi_release_wrapper + * + * Description: + * Release Wi-Fi coexistence. + * + * Input Parameters: + * event - WiFi event + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned + * on failure. + * + ****************************************************************************/ + +static IRAM_ATTR int32_t coex_wifi_release_wrapper(uint32_t event) +{ + return 0; +} + +/**************************************************************************** + * Name: coex_wifi_channel_set_wrapper + * + * Description: + * Set Wi-Fi channel to coexistence module. + * + * Input Parameters: + * primary - WiFi primary channel + * secondary - WiFi secondary channel + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned + * on failure. + * + ****************************************************************************/ + +static int coex_wifi_channel_set_wrapper(uint8_t primary, uint8_t secondary) +{ + return 0; +} + +/**************************************************************************** + * Name: coex_event_duration_get_wrapper + * + * Description: + * Get coexistence event duration. + * + * Input Parameters: + * event - Coexistence event + * duration - Coexistence event duration + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned + * on failure. + * + ****************************************************************************/ + +static int coex_event_duration_get_wrapper(uint32_t event, + uint32_t *duration) +{ + return 0; +} + +/**************************************************************************** + * Name: coex_pti_get_wrapper + * + * Description: + * Get coexistence event priority. + * + * Input Parameters: + * event - Coexistence event + * pti - Coexistence event priority + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned + * on failure. + * + ****************************************************************************/ + +static int coex_pti_get_wrapper(uint32_t event, uint8_t *pti) +{ + return 0; +} + +/**************************************************************************** + * Name: coex_schm_status_bit_clear_wrapper + * + * Description: + * Clear coexistence status. + * + * Input Parameters: + * type - Coexistence status type + * status - Coexistence status + * + * Returned Value: + * none + * + ****************************************************************************/ + +static void coex_schm_status_bit_clear_wrapper(uint32_t type, + uint32_t status) +{ +} + +/**************************************************************************** + * Name: coex_schm_status_bit_set_wrapper + * + * Description: + * Set coexistence status. + * + * Input Parameters: + * type - Coexistence status type + * status - Coexistence status + * + * Returned Value: + * none + * + ****************************************************************************/ + +static void coex_schm_status_bit_set_wrapper(uint32_t type, uint32_t status) +{ +} + +/**************************************************************************** + * Name: coex_schm_interval_set_wrapper + * + * Description: + * Set coexistence scheme interval. + * + * Input Parameters: + * interval - Coexistence scheme interval + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned + * on failure. + * + ****************************************************************************/ + +static IRAM_ATTR int coex_schm_interval_set_wrapper(uint32_t interval) +{ + return 0; +} + +/**************************************************************************** + * Name: coex_schm_interval_get_wrapper + * + * Description: + * Get coexistence scheme interval. + * + * Input Parameters: + * none + * + * Returned Value: + * Coexistence scheme interval + * + ****************************************************************************/ + +static uint32_t coex_schm_interval_get_wrapper(void) +{ + return 0; +} + +/**************************************************************************** + * Name: coex_schm_curr_period_get_wrapper + * + * Description: + * Get current coexistence scheme period. + * + * Input Parameters: + * none + * + * Returned Value: + * Coexistence scheme period + * + ****************************************************************************/ + +static uint8_t coex_schm_curr_period_get_wrapper(void) +{ + return 0; +} + +/**************************************************************************** + * Name: coex_schm_curr_phase_get_wrapper + * + * Description: + * Get current coexistence scheme phase. + * + * Input Parameters: + * none + * + * Returned Value: + * Coexistence scheme phase + * + ****************************************************************************/ + +static void *coex_schm_curr_phase_get_wrapper(void) +{ + return NULL; +} + +/**************************************************************************** + * Name: coex_register_start_cb_wrapper + * + * Description: + * Register Wi-Fi callback for coexistence starts. + * + * Input Parameters: + * cb - WiFi callback + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned + * on failure. + * + ****************************************************************************/ + +static int coex_register_start_cb_wrapper(int (* cb)(void)) +{ + return 0; +} + +/**************************************************************************** + * Name: coex_schm_process_restart_wrapper + * + * Description: + * Restart current coexistence scheme. + * + * Input Parameters: + * none + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned + * on failure. + * + ****************************************************************************/ + +static int coex_schm_process_restart_wrapper(void) +{ + return 0; +} + +/**************************************************************************** + * Name: coex_schm_register_cb_wrapper + * + * Description: + * Register callback for coexistence scheme. + * + * Input Parameters: + * type - callback type + * callback - callback + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned + * on failure. + * + ****************************************************************************/ + +static int coex_schm_register_cb_wrapper(int type, int(*cb)(int)) +{ + return 0; +} + +/**************************************************************************** + * Name: coex_schm_flexible_period_set_wrapper + * + * Description: + * This is a wrapper for coex_schm_flexible_period_set. It sets the + * flexible period for the coexistence mechanism. If power management + * feature is enabled (CONFIG_ESP_COEX_POWER_MANAGEMENT), it calls the + * function with the given period. If the feature is not enabled, it + * returns 0. + * + * Input Parameters: + * period - The period to set for the coexistence mechanism. + * + * Returned Value: + * If power management is enabled, it returns the result of the + * coex_schm_flexible_period_set function. Otherwise, it returns 0. + * + ****************************************************************************/ + +static int coex_schm_flexible_period_set_wrapper(uint8_t period) +{ +#if CONFIG_ESP_COEX_POWER_MANAGEMENT + return coex_schm_flexible_period_set(period); +#else + return 0; +#endif +} + +/**************************************************************************** + * Name: coex_schm_flexible_period_get_wrapper + * + * Description: + * This is a wrapper for coex_schm_flexible_period_get. If power management + * feature is enabled (CONFIG_ESP_COEX_POWER_MANAGEMENT), it calls the + * function and returns its result. If the feature is not enabled, it + * returns 1. + * + * Input Parameters: + * None + * + * Returned Value: + * If power management is enabled, it returns the result of the + * coex_schm_flexible_period_get function. Otherwise, it returns 1. + * + ****************************************************************************/ + +static uint8_t coex_schm_flexible_period_get_wrapper(void) +{ +#if CONFIG_ESP_COEX_POWER_MANAGEMENT + return coex_schm_flexible_period_get(); +#else + return 1; +#endif +} + +/**************************************************************************** + * Name: esp_random_ulong + * + * Description: + * Get random value and convert to unsigned long. + * + * Input Parameters: + * None + * + * Returned Value: + * Random value + * + ****************************************************************************/ + +static unsigned long esp_random_ulong(void) +{ + return esp_random(); +} + +/**************************************************************************** + * Name: esp_wifi_tx_done_cb + * + * Description: + * Wi-Fi TX done callback function. + * + * Input Parameters: + * ifidx - The interface id that the tx callback has been triggered from + * data - Pointer to the data transmitted + * data_len - Length of the data transmitted + * txstatus - True:if the data was transmitted sucessfully False: if data + * transmission failed + * + * Returned Value: + * none + * + ****************************************************************************/ + +static IRAM_ATTR void esp_wifi_tx_done_cb(uint8_t ifidx, uint8_t *data, + uint16_t *len, bool txstatus) +{ +#ifdef ESPRESSIF_WLAN_HAS_STA + if (ifidx == ESP_IF_WIFI_STA) + { + if (g_sta_txdone_cb) + { + g_sta_txdone_cb(data, len, txstatus); + } + } + else +#endif /* ESPRESSIF_WLAN_HAS_STA */ + +#ifdef ESPRESSIF_WLAN_HAS_SOFTAP + if (ifidx == ESP_IF_WIFI_AP) + { + if (g_softap_txdone_cb) + { + g_softap_txdone_cb(data, len, txstatus); + } + } + else +#endif /* ESPRESSIF_WLAN_HAS_SOFTAP */ + { + wlerr("ifidx=%d is error\n", ifidx); + } +} + +#ifdef ESPRESSIF_WLAN_HAS_STA + +/**************************************************************************** + * Name: esp_wifi_auth_trans + * + * Description: + * Converts a ESP32-S2 authenticate mode values to WEXT authenticate mode. + * + * Input Parameters: + * wifi_auth - ESP32-S2 authenticate mode + * + * Returned Value: + * authenticate mode + * + ****************************************************************************/ + +static int esp_wifi_auth_trans(uint32_t wifi_auth) +{ + int auth_mode = IW_AUTH_WPA_VERSION_DISABLED; + + switch (wifi_auth) + { + case WIFI_AUTH_OPEN: + auth_mode = IW_AUTH_WPA_VERSION_DISABLED; + break; + + case WIFI_AUTH_WPA_PSK: + auth_mode = IW_AUTH_WPA_VERSION_WPA; + break; + + case WIFI_AUTH_WPA2_PSK: + case WIFI_AUTH_WPA_WPA2_PSK: + auth_mode = IW_AUTH_WPA_VERSION_WPA2; + break; + + case WIFI_AUTH_WPA3_PSK: + case WIFI_AUTH_WPA2_WPA3_PSK: + auth_mode = IW_AUTH_WPA_VERSION_WPA3; + break; + + default: + wlerr("Failed to transfer wireless authmode: %d", wifi_auth); + break; + } + + return auth_mode; +} + +/**************************************************************************** + * Name: esp_wifi_cipher_trans + * + * Description: + * Converts a ESP32-S2 cipher type values to WEXT cipher type values. + * + * Input Parameters: + * wifi_cipher - ESP32-S2 cipher type + * + * Returned Value: + * cipher type + * + ****************************************************************************/ + +static int esp_wifi_cipher_trans(uint32_t wifi_cipher) +{ + int cipher_mode = IW_AUTH_CIPHER_NONE; + + switch (wifi_cipher) + { + case WIFI_CIPHER_TYPE_NONE: + cipher_mode = IW_AUTH_CIPHER_NONE; + break; + + case WIFI_CIPHER_TYPE_WEP40: + cipher_mode = IW_AUTH_CIPHER_WEP40; + break; + + case WIFI_CIPHER_TYPE_WEP104: + cipher_mode = IW_AUTH_CIPHER_WEP104; + break; + + case WIFI_CIPHER_TYPE_TKIP: + cipher_mode = IW_AUTH_CIPHER_TKIP; + break; + + case WIFI_CIPHER_TYPE_CCMP: + case WIFI_CIPHER_TYPE_TKIP_CCMP: + cipher_mode = IW_AUTH_CIPHER_CCMP; + break; + + case WIFI_CIPHER_TYPE_AES_CMAC128: + cipher_mode = IW_AUTH_CIPHER_AES_CMAC; + break; + + default: + wlerr("Failed to transfer wireless authmode: %d", + wifi_cipher); + break; + } + + return cipher_mode; +} + +#endif /* ESPRESSIF_WLAN_HAS_STA */ + +/**************************************************************************** + * Name: esp_freq_to_channel + * + * Description: + * Converts Wi-Fi frequency to channel. + * + * Input Parameters: + * freq - Wi-Fi frequency + * + * Returned Value: + * Wi-Fi channel + * + ****************************************************************************/ + +static int esp_freq_to_channel(uint16_t freq) +{ + int channel = 0; + if (freq >= 2412 && freq <= 2484) + { + if (freq == 2484) + { + channel = 14; + } + else + { + channel = freq - 2407; + if (channel % 5) + { + return 0; + } + + channel /= 5; + } + + return channel; + } + + if (freq >= 5005 && freq < 5900) + { + if (freq % 5) + { + return 0; + } + + channel = (freq - 5000) / 5; + return channel; + } + + if (freq >= 4905 && freq < 5000) + { + if (freq % 5) + { + return 0; + } + + channel = (freq - 4000) / 5; + return channel; + } + + return 0; +} + +/**************************************************************************** + * Functions needed by libpp.a + ****************************************************************************/ + +/**************************************************************************** + * Name: pp_printf + * + * Description: + * Output format string and its arguments + * + * Input Parameters: + * format - format string + * + * Returned Value: + * Zero (OK) + * + ****************************************************************************/ + +int pp_printf(const char *format, ...) +{ +#ifdef CONFIG_DEBUG_WIRELESS_INFO + va_list arg; + + va_start(arg, format); + vsyslog(LOG_INFO, format, arg); + va_end(arg); +#endif + + return 0; +} + +/**************************************************************************** + * Functions needed by libnet80211.a + ****************************************************************************/ + +/**************************************************************************** + * Name: net80211_printf + * + * Description: + * Output format string and its arguments + * + * Input Parameters: + * format - format string + * + * Returned Value: + * Zero (OK) + * + ****************************************************************************/ + +int net80211_printf(const char *format, ...) +{ +#ifdef CONFIG_DEBUG_WIRELESS_INFO + va_list arg; + + va_start(arg, format); + vsyslog(LOG_INFO, format, arg); + va_end(arg); +#endif + + return 0; +} + +/**************************************************************************** + * Functions needed by libcoexist.a + ****************************************************************************/ + +/**************************************************************************** + * Name: coexist_printf + * + * Description: + * Output format string and its arguments + * + * Input Parameters: + * format - format string + * + * Returned Value: + * Zero (OK) + * + ****************************************************************************/ + +int coexist_printf(const char *format, ...) +{ +#ifdef CONFIG_DEBUG_WIRELESS_INFO + va_list arg; + + va_start(arg, format); + vsyslog(LOG_INFO, format, arg); + va_end(arg); +#endif + + return 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: esp_event_send_internal + * + * Description: + * Post event message to queue + * + * Input Parameters: + * event_base - Event set name + * event_id - Event ID + * event_data - Event private data + * event_data_size - Event data size + * ticks_to_wait - Waiting system ticks + * + * Returned Value: + * Task maximum priority + * + ****************************************************************************/ + +int32_t esp_event_send_internal(esp_event_base_t event_base, + int32_t event_id, + void *event_data, + size_t event_data_size, + uint32_t ticks_to_wait) +{ + int32_t ret; + + ret = esp_event_post(event_base, event_id, event_data, + event_data_size, ticks_to_wait); + + return ret; +} + +/**************************************************************************** + * Name: esp_wifi_free_eb + * + * Description: + * Free Wi-Fi receive callback input eb pointer + * + * Input Parameters: + * eb - Wi-Fi receive callback input eb pointer + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp_wifi_free_eb(void *eb) +{ + esp_wifi_internal_free_rx_buffer(eb); +} + +/**************************************************************************** + * Name: esp_wifi_notify_subscribe + * + * Description: + * Enable event notification + * + * Input Parameters: + * pid - Task PID + * event - Signal event data pointer + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_notify_subscribe(pid_t pid, struct sigevent *event) +{ + int id; + struct wifi_notify *notify; + int ret = -1; + + wlinfo("PID=%d event=%p\n", pid, event); + + esp_wifi_lock(true); + + if (event->sigev_notify == SIGEV_SIGNAL) + { + id = esp_event_id_map(event->sigev_signo); + if (id < 0) + { + wlerr("No process event %d\n", event->sigev_signo); + } + else + { + notify = &g_wifi_notify[id]; + + if (notify->assigned) + { + wlerr("sigev_signo %d has subscribed\n", + event->sigev_signo); + } + else + { + if (pid == 0) + { + pid = nxsched_gettid(); + wlinfo("Actual PID=%d\n", pid); + } + + notify->pid = pid; + notify->event = *event; + notify->assigned = true; + + ret = 0; + } + } + } + else if (event->sigev_notify == SIGEV_NONE) + { + id = esp_event_id_map(event->sigev_signo); + if (id < 0) + { + wlerr("No process event %d\n", event->sigev_signo); + } + else + { + notify = &g_wifi_notify[id]; + + if (!notify->assigned) + { + wlerr("sigev_signo %d has not subscribed\n", + event->sigev_signo); + } + else + { + notify->assigned = false; + + ret = 0; + } + } + } + else + { + wlerr("sigev_notify %d is invalid\n", event->sigev_signo); + } + + esp_wifi_lock(false); + + return ret; +} + +/**************************************************************************** + * Name: esp_wifi_adapter_init + * + * Description: + * Initialize ESP32-S2 Wi-Fi adapter + * + * Input Parameters: + * None + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_adapter_init(void) +{ + int ret; + wifi_init_config_t wifi_cfg = WIFI_INIT_CONFIG_DEFAULT(); + + esp_wifi_lock(true); + + if (g_wifi_ref) + { + wlinfo("Wi-Fi adapter is already initialized\n"); + g_wifi_ref++; + esp_wifi_lock(false); + return OK; + } + + sq_init(&g_wifi_evt_queue); + + wifi_cfg.nvs_enable = 0; + +#ifdef CONFIG_ESPRESSIF_WIFI_TX_AMPDU + wifi_cfg.ampdu_tx_enable = 1; +#else + wifi_cfg.ampdu_tx_enable = 0; +#endif + +#ifdef CONFIG_ESPRESSIF_WIFI_RX_AMPDU + wifi_cfg.ampdu_rx_enable = 1; +#else + wifi_cfg.ampdu_rx_enable = 0; +#endif + +#ifdef CONFIG_ESPRESSIF_WIFI_STA_DISCONNECT_PM + wifi_cfg.sta_disconnected_pm = true; +#else + wifi_cfg.sta_disconnected_pm = false; +#endif + + wifi_cfg.rx_ba_win = CONFIG_ESPRESSIF_WIFI_RXBA_AMPDU_WZ; + wifi_cfg.static_rx_buf_num = CONFIG_ESPRESSIF_WIFI_STATIC_RXBUF_NUM; + wifi_cfg.dynamic_rx_buf_num = CONFIG_ESPRESSIF_WIFI_DYNAMIC_RXBUF_NUM; + wifi_cfg.dynamic_tx_buf_num = CONFIG_ESPRESSIF_WIFI_DYNAMIC_TXBUF_NUM; + + ret = esp_wifi_init(&wifi_cfg); + if (ret) + { + wlerr("Failed to initialize Wi-Fi error=%d\n", ret); + ret = wifi_errno_trans(ret); + goto errout_init_wifi; + } + + ret = esp_wifi_set_tx_done_cb(esp_wifi_tx_done_cb); + if (ret) + { + wlerr("Failed to register TX done callback ret=%d\n", ret); + ret = wifi_errno_trans(ret); + goto errout_init_txdone; + } + + g_wifi_ref++; + + wlinfo("OK to initialize Wi-Fi adapter\n"); + + esp_wifi_lock(false); + + return OK; + +errout_init_txdone: + esp_wifi_deinit(); +errout_init_wifi: + esp_wifi_lock(false); + + return ret; +} + +/**************************************************************************** + * Station functions + ****************************************************************************/ + +#ifdef ESPRESSIF_WLAN_HAS_STA + +/**************************************************************************** + * Name: esp_wifi_sta_start + * + * Description: + * Start Wi-Fi station. + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_start(void) +{ + int ret; + wifi_mode_t mode; + + esp_wifi_lock(true); + + ret = esp_wifi_stop(); + if (ret) + { + wlinfo("Failed to stop Wi-Fi ret=%d\n", ret); + } + +#ifdef ESPRESSIF_WLAN_HAS_SOFTAP + if (g_softap_started) + { + mode = WIFI_MODE_APSTA; + } + else +#endif /* ESPRESSIF_WLAN_HAS_SOFTAP */ + { + mode = WIFI_MODE_STA; + } + + ret = esp_wifi_set_mode(mode); + if (ret) + { + wlerr("Failed to set Wi-Fi mode=%d ret=%d\n", mode, ret); + ret = wifi_errno_trans(ret); + goto errout; + } + + ret = esp_wifi_start(); + if (ret) + { + wlerr("Failed to start Wi-Fi with mode=%d ret=%d\n", mode, ret); + ret = wifi_errno_trans(ret); + goto errout; + } + + g_sta_started = true; + + wlinfo("OK to start Wi-Fi station\n"); + +errout: + esp_wifi_lock(false); + return ret; +} + +/**************************************************************************** + * Name: esp_wifi_sta_stop + * + * Description: + * Stop Wi-Fi station. + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_stop(void) +{ + int ret; + + esp_wifi_lock(true); + + ret = esp_wifi_stop(); + if (ret) + { + wlinfo("Failed to stop Wi-Fi ret=%d\n", ret); + } + + g_sta_started = false; + +#ifdef ESPRESSIF_WLAN_HAS_SOFTAP + if (g_softap_started) + { + ret = esp_wifi_set_mode(WIFI_MODE_AP); + if (ret) + { + wlerr("Failed to set Wi-Fi AP mode ret=%d\n", ret); + ret = wifi_errno_trans(ret); + goto errout; + } + + ret = esp_wifi_start(); + if (ret) + { + wlerr("Failed to start Wi-Fi AP ret=%d\n", ret); + ret = wifi_errno_trans(ret); + goto errout; + } + } +#endif /* ESPRESSIF_WLAN_HAS_SOFTAP */ + + wlinfo("OK to stop Wi-Fi station\n"); + +#ifdef ESPRESSIF_WLAN_HAS_SOFTAP +errout: +#endif /* ESPRESSIF_WLAN_HAS_SOFTAP */ + + esp_wifi_lock(false); + return ret; +} + +/**************************************************************************** + * Name: esp_wifi_sta_send_data + * + * Description: + * Use Wi-Fi station interface to send 802.3 frame + * + * Input Parameters: + * pbuf - Packet buffer pointer + * len - Packet length + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_send_data(void *pbuf, uint32_t len) +{ + int ret; + + ret = esp_wifi_internal_tx(WIFI_IF_STA, pbuf, len); + + return wifi_errno_trans(ret); +} + +/**************************************************************************** + * Name: esp_wifi_sta_register_recv_cb + * + * Description: + * Register Wi-Fi station receive packet callback function + * + * Input Parameters: + * recv_cb - Receive callback function + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_register_recv_cb(int (*recv_cb)(void *buffer, + uint16_t len, + void *eb)) +{ + int ret; + + ret = esp_wifi_internal_reg_rxcb(ESP_IF_WIFI_STA, (wifi_rxcb_t)recv_cb); + + return wifi_errno_trans(ret); +} + +/**************************************************************************** + * Name: esp_wifi_sta_register_txdone_cb + * + * Description: + * Register the station TX done callback function. + * + * Input Parameters: + * cb - The callback function + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp_wifi_sta_register_txdone_cb(wifi_txdone_cb_t cb) +{ + g_sta_txdone_cb = cb; +} + +/**************************************************************************** + * Name: esp_wifi_sta_read_mac + * + * Description: + * Read station interface MAC address from efuse + * + * Input Parameters: + * mac - MAC address buffer pointer + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_sta_read_mac(uint8_t *mac) +{ + return esp_read_mac(mac, ESP_MAC_WIFI_STA); +} + +/**************************************************************************** + * Name: esp_wifi_set_password + * + * Description: + * Set/Get Wi-Fi station password + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_password(struct iwreq *iwr, bool set) +{ + int ret; + int size; + wifi_config_t wifi_cfg; + struct iw_encode_ext *ext = iwr->u.encoding.pointer; + uint8_t *pdata; + uint8_t len; +#ifdef CONFIG_DEBUG_WIRELESS_INFO + char buf[PWD_MAX_LEN + 1]; +#endif + + DEBUGASSERT(ext != NULL); + + pdata = ext->key; + + wifi_cfg = g_sta_wifi_cfg; + + if (set) + { + len = ext->key_len; + if (len > PWD_MAX_LEN) + { + return -EINVAL; + } + + memset(wifi_cfg.sta.password, 0x0, PWD_MAX_LEN); + + if (ext->alg != IW_ENCODE_ALG_NONE) + { + memcpy(wifi_cfg.sta.password, pdata, len); + } + + wifi_cfg.sta.pmf_cfg.capable = true; + wifi_cfg.sta.listen_interval = DEFAULT_LISTEN_INTERVAL; + + if (g_sta_connected) + { + ret = esp_wifi_sta_disconnect(); + if (ret) + { + wlerr("Failed to disconnect from Wi-Fi AP ret=%d\n", ret); + return ret; + } + + ret = esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg); + if (ret) + { + wlerr("Failed to set Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + ret = esp_wifi_sta_connect(); + if (ret) + { + wlerr("Failed to connect to Wi-Fi AP ret=%d\n", ret); + return ret; + } + } + + g_sta_wifi_cfg = wifi_cfg; + } + else + { + len = iwr->u.encoding.length - sizeof(*ext); + size = strnlen((char *)wifi_cfg.sta.password, PWD_MAX_LEN); + if (len < size) + { + return -EINVAL; + } + else + { + ext->key_len = size; + memcpy(pdata, wifi_cfg.sta.password, ext->key_len); + } + + if (g_sta_connected) + { + wifi_ap_record_t ap_info; + + ret = esp_wifi_sta_get_ap_info(&ap_info); + if (ret) + { + wlerr("Failed to get AP record ret=%d", ret); + return wifi_errno_trans(ret); + } + + switch (ap_info.pairwise_cipher) + { + case WIFI_CIPHER_TYPE_NONE: + ext->alg = IW_ENCODE_ALG_NONE; + break; + + case WIFI_CIPHER_TYPE_WEP40: + case WIFI_CIPHER_TYPE_WEP104: + ext->alg = IW_ENCODE_ALG_WEP; + break; + + case WIFI_CIPHER_TYPE_TKIP: + ext->alg = IW_ENCODE_ALG_TKIP; + break; + + case WIFI_CIPHER_TYPE_CCMP: + case WIFI_CIPHER_TYPE_TKIP_CCMP: + ext->alg = IW_ENCODE_ALG_CCMP; + break; + + case WIFI_CIPHER_TYPE_AES_CMAC128: + ext->alg = IW_ENCODE_ALG_AES_CMAC; + break; + + default: + wlerr("Failed to transfer wireless authmode: %d", + ap_info.pairwise_cipher); + return -EIO; + } + } + } + +#ifdef CONFIG_DEBUG_WIRELESS_INFO + memcpy(buf, pdata, len); + buf[len] = 0; + wlinfo("Wi-Fi station password=%s len=%d\n", buf, len); +#endif + + return OK; +} + +/**************************************************************************** + * Name: esp_wifi_sta_essid + * + * Description: + * Set/Get Wi-Fi station ESSID + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_essid(struct iwreq *iwr, bool set) +{ + int ret; + int size; + wifi_config_t wifi_cfg; + struct iw_point *essid = &iwr->u.essid; + uint8_t *pdata; + uint8_t len; +#ifdef CONFIG_DEBUG_WIRELESS_INFO + char buf[SSID_MAX_LEN + 1]; +#endif + + DEBUGASSERT(essid != NULL); + + pdata = essid->pointer; + len = essid->length; + + if (set && len > SSID_MAX_LEN) + { + return -EINVAL; + } + + wifi_cfg = g_sta_wifi_cfg; + + if (set) + { + memset(wifi_cfg.sta.ssid, 0x0, SSID_MAX_LEN); + memcpy(wifi_cfg.sta.ssid, pdata, len); + memset(wifi_cfg.sta.sae_h2e_identifier, 0x0, SAE_H2E_IDENTIFIER_LEN); + wifi_cfg.sta.sae_pwe_h2e = WPA3_SAE_PWE_BOTH; + + if (g_sta_connected) + { + ret = esp_wifi_sta_disconnect(); + if (ret) + { + wlerr("Failed to disconnect from Wi-Fi AP ret=%d\n", ret); + return ret; + } + + ret = esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg); + if (ret) + { + wlerr("Failed to set Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + ret = esp_wifi_sta_connect(); + if (ret) + { + wlerr("Failed to connect to Wi-Fi AP ret=%d\n", ret); + return ret; + } + } + + g_sta_wifi_cfg = wifi_cfg; + } + else + { + size = strnlen((char *)wifi_cfg.sta.ssid, SSID_MAX_LEN); + if (len < size) + { + return -EINVAL; + } + else + { + len = size; + memcpy(pdata, wifi_cfg.sta.ssid, len); + } + + if (g_sta_connected) + { + essid->flags = IW_ESSID_ON; + } + else + { + essid->flags = IW_ESSID_OFF; + } + } + +#ifdef CONFIG_DEBUG_WIRELESS_INFO + memcpy(buf, pdata, len); + buf[len] = 0; + wlinfo("Wi-Fi station ssid=%s len=%d\n", buf, len); +#endif + + return OK; +} + +/**************************************************************************** + * Name: esp_wifi_sta_bssid + * + * Description: + * Set/Get Wi-Fi station BSSID + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_bssid(struct iwreq *iwr, bool set) +{ + int ret; + wifi_config_t wifi_cfg; + struct sockaddr *sockaddr; + char *pdata; + + sockaddr = &iwr->u.ap_addr; + pdata = sockaddr->sa_data; + + wifi_cfg = g_sta_wifi_cfg; + + if (set) + { + wifi_cfg.sta.bssid_set = true; + memcpy(wifi_cfg.sta.bssid, pdata, MAC_LEN); + + if (g_sta_connected) + { + ret = esp_wifi_sta_disconnect(); + if (ret) + { + wlerr("Failed to disconnect from Wi-Fi AP ret=%d\n", ret); + return ret; + } + + ret = esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg); + if (ret) + { + wlerr("Failed to set Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + ret = esp_wifi_sta_connect(); + if (ret) + { + wlerr("Failed to connect to Wi-Fi AP ret=%d\n", ret); + return ret; + } + } + + g_sta_wifi_cfg = wifi_cfg; + } + else + { + memcpy(pdata, wifi_cfg.sta.bssid, MAC_LEN); + } + + return OK; +} + +/**************************************************************************** + * Name: esp_wifi_sta_connect + * + * Description: + * Trigger Wi-Fi station connection action + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_connect(void) +{ + int ret; + uint32_t ticks; + + esp_wifi_lock(true); + + if (g_sta_connected) + { + wlinfo("Wi-Fi has connected AP\n"); + esp_wifi_lock(false); + return OK; + } + + g_sta_reconnect = true; + + ret = esp_wifi_set_config(WIFI_IF_STA, &g_sta_wifi_cfg); + if (ret) + { + wlerr("Failed to set Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + ret = esp_wifi_connect(); + if (ret) + { + wlerr("Failed to connect ret=%d\n", ret); + ret = wifi_errno_trans(ret); + goto errout; + } + + esp_wifi_lock(false); + + ticks = SEC2TICK(WIFI_CONNECT_TIMEOUT); + do + { + if (g_sta_connected) + { + break; + } + + esp_task_delay(1); + } + while (ticks--); + + if (!g_sta_connected) + { + g_sta_reconnect = false; + wlinfo("Failed to connect to AP\n"); + return -1; + } + + return OK; + +errout: + g_sta_reconnect = false; + esp_wifi_lock(false); + return ret; +} + +/**************************************************************************** + * Name: esp_wifi_sta_disconnect + * + * Description: + * Trigger Wi-Fi station disconnection action + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_disconnect(void) +{ + int ret; + + esp_wifi_lock(true); + + g_sta_reconnect = false; + + ret = esp_wifi_disconnect(); + if (ret) + { + wlerr("Failed to disconnect ret=%d\n", ret); + ret = wifi_errno_trans(ret); + } + else + { + wlinfo("OK to disconnect Wi-Fi station\n"); + } + + esp_wifi_lock(false); + return ret; +} + +/**************************************************************************** + * Name: esp_wifi_sta_mode + * + * Description: + * Set/Get Wi-Fi Station mode code. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_mode(struct iwreq *iwr, bool set) +{ + if (set == false) + { + iwr->u.mode = IW_MODE_INFRA; + } + + return OK; +} + +/**************************************************************************** + * Name: esp_wifi_sta_auth + * + * Description: + * Set/Get station authentication mode params. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_auth(struct iwreq *iwr, bool set) +{ + int ret; + int cmd; + wifi_config_t wifi_cfg; + wifi_ap_record_t ap_info; + + wifi_cfg = g_sta_wifi_cfg; + + if (set) + { + cmd = iwr->u.param.flags & IW_AUTH_INDEX; + switch (cmd) + { + case IW_AUTH_WPA_VERSION: + { + switch (iwr->u.param.value) + { + case IW_AUTH_WPA_VERSION_DISABLED: + wifi_cfg.sta.threshold.authmode = WIFI_AUTH_OPEN; + break; + + case IW_AUTH_WPA_VERSION_WPA: + wifi_cfg.sta.threshold.authmode = WIFI_AUTH_WPA_PSK; + break; + + case IW_AUTH_WPA_VERSION_WPA2: + wifi_cfg.sta.threshold.authmode = WIFI_AUTH_WPA2_PSK; + break; + + case IW_AUTH_WPA_VERSION_WPA3: + wifi_cfg.sta.threshold.authmode = WIFI_AUTH_WPA3_PSK; + break; + + default: + wlerr("Invalid wpa version %" PRId32 "\n", + iwr->u.param.value); + return -EINVAL; + } + } + + break; + case IW_AUTH_CIPHER_PAIRWISE: + case IW_AUTH_CIPHER_GROUP: + { + switch (iwr->u.param.value) + { + case IW_AUTH_CIPHER_NONE: + wifi_cfg.sta.threshold.authmode = WIFI_AUTH_OPEN; + break; + + case IW_AUTH_CIPHER_WEP40: + case IW_AUTH_CIPHER_WEP104: + wifi_cfg.sta.threshold.authmode = WIFI_AUTH_WEP; + break; + + case IW_AUTH_CIPHER_TKIP: + case IW_AUTH_CIPHER_CCMP: + case IW_AUTH_CIPHER_AES_CMAC: + break; + + default: + wlerr("Invalid cipher mode %" PRId32 "\n", + iwr->u.param.value); + return -EINVAL; + } + } + + break; + case IW_AUTH_KEY_MGMT: + case IW_AUTH_TKIP_COUNTERMEASURES: + case IW_AUTH_DROP_UNENCRYPTED: + case IW_AUTH_80211_AUTH_ALG: + case IW_AUTH_WPA_ENABLED: + case IW_AUTH_RX_UNENCRYPTED_EAPOL: + case IW_AUTH_ROAMING_CONTROL: + case IW_AUTH_PRIVACY_INVOKED: + default: + wlerr("Unknown cmd %d\n", cmd); + return -EINVAL; + } + + size_t password_len = strlen((const char *)wifi_cfg.sta.password); + wifi_auth_mode_t authmode = wifi_cfg.sta.threshold.authmode; + + if (g_sta_connected && + ((password_len > 0 && authmode != WIFI_AUTH_OPEN) || + (password_len == 0 && authmode == WIFI_AUTH_OPEN))) + { + ret = esp_wifi_sta_disconnect(); + if (ret) + { + wlerr("Failed to disconnect from Wi-Fi AP ret=%d\n", ret); + return ret; + } + + ret = esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg); + if (ret) + { + wlerr("Failed to set Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + ret = esp_wifi_sta_connect(); + if (ret) + { + wlerr("Failed to connect to Wi-Fi AP ret=%d\n", ret); + return ret; + } + } + + g_sta_wifi_cfg = wifi_cfg; + } + else + { + if (g_sta_connected == false) + { + return -ENOTCONN; + } + + ret = esp_wifi_sta_get_ap_info(&ap_info); + if (ret) + { + wlerr("Failed to get AP record ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + cmd = iwr->u.param.flags & IW_AUTH_INDEX; + switch (cmd) + { + case IW_AUTH_WPA_VERSION: + iwr->u.param.value = esp_wifi_auth_trans(ap_info.authmode); + break; + + case IW_AUTH_CIPHER_PAIRWISE: + iwr->u.param.value = + esp_wifi_cipher_trans(ap_info.pairwise_cipher); + break; + + case IW_AUTH_CIPHER_GROUP: + iwr->u.param.value = esp_wifi_cipher_trans(ap_info.group_cipher); + break; + + case IW_AUTH_KEY_MGMT: + case IW_AUTH_TKIP_COUNTERMEASURES: + case IW_AUTH_DROP_UNENCRYPTED: + case IW_AUTH_80211_AUTH_ALG: + case IW_AUTH_WPA_ENABLED: + case IW_AUTH_RX_UNENCRYPTED_EAPOL: + case IW_AUTH_ROAMING_CONTROL: + case IW_AUTH_PRIVACY_INVOKED: + default: + wlerr("Unknown cmd %d\n", cmd); + return -ENOSYS; + } + } + + return OK; +} + +/**************************************************************************** + * Name: esp_wifi_sta_freq + * + * Description: + * Set/Get station frequency. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_freq(struct iwreq *iwr, bool set) +{ + int ret; + + if (set && (iwr->u.freq.flags == IW_FREQ_FIXED)) + { + wifi_config_t wifi_cfg = g_sta_wifi_cfg; + + wifi_cfg.sta.channel = esp_freq_to_channel(iwr->u.freq.m); + + if (g_sta_connected) + { + ret = esp_wifi_sta_disconnect(); + if (ret) + { + wlerr("Failed to disconnect from Wi-Fi AP ret=%d\n", ret); + return ret; + } + + ret = esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg); + if (ret) + { + wlerr("Failed to set Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + ret = esp_wifi_sta_connect(); + if (ret) + { + wlerr("Failed to connect to Wi-Fi AP ret=%d\n", ret); + return ret; + } + } + + g_sta_wifi_cfg = wifi_cfg; + } + else + { + if (g_sta_connected) + { + wifi_ap_record_t ap_info; + + ret = esp_wifi_sta_get_ap_info(&ap_info); + if (ret) + { + wlerr("Failed to get AP record ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + iwr->u.freq.flags = IW_FREQ_FIXED; + iwr->u.freq.e = 0; + iwr->u.freq.m = 2407 + 5 * ap_info.primary; + } + else + { + iwr->u.freq.flags = IW_FREQ_AUTO; + iwr->u.freq.e = 0; + iwr->u.freq.m = 2412; + } + } + + return OK; +} + +/**************************************************************************** + * Name: esp_wifi_sta_bitrate + * + * Description: + * Get station default bit rate (Mbps). + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_bitrate(struct iwreq *iwr, bool set) +{ + int ret; + wifi_ap_record_t ap_info; + + if (set) + { + return -ENOSYS; + } + else + { + if (g_sta_connected == false) + { + iwr->u.bitrate.fixed = IW_FREQ_AUTO; + return OK; + } + + ret = esp_wifi_sta_get_ap_info(&ap_info); + if (ret) + { + wlerr("Failed to get AP record ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + iwr->u.bitrate.fixed = IW_FREQ_FIXED; + if (ap_info.phy_11n) + { + if (ap_info.second) + { + iwr->u.bitrate.value = ESP_WIFI_11N_MCS7_HT40_BITRATE; + } + else + { + iwr->u.bitrate.value = ESP_WIFI_11N_MCS7_HT20_BITRATE; + } + } + else if (ap_info.phy_11g) + { + iwr->u.bitrate.value = ESP_WIFI_11G_MAX_BITRATE; + } + else if (ap_info.phy_11b) + { + iwr->u.bitrate.value = ESP_WIFI_11B_MAX_BITRATE; + } + else + { + return -EIO; + } + } + + return OK; +} + +#endif /* ESPRESSIF_WLAN_HAS_STA */ + +/**************************************************************************** + * Name: esp_wifi_sta_get_txpower + * + * Description: + * Get station transmit power (dBm). + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_txpower(struct iwreq *iwr, bool set) +{ + int ret; + int8_t power; + double power_dbm; + + if (set) + { + if (iwr->u.txpower.flags == IW_TXPOW_RELATIVE) + { + power = (int8_t)iwr->u.txpower.value; + } + else + { + if (iwr->u.txpower.flags == IW_TXPOW_MWATT) + { + power_dbm = ceil(10 * log10(iwr->u.txpower.value)); + } + else + { + power_dbm = iwr->u.txpower.value; + } + + power = (int8_t)(power_dbm * 4); + } + + /* The value set by this API will be mapped to the max_tx_power + * of the structure wifi_country_t variable. Param power unit is + * 0.25dBm, range is [8, 84] corresponding to 2dBm - 20dBm. + * Relationship between set value and actual value. + * As follows: {set value range, actual value} = + * {{[8, 19],8}, {[20, 27],20}, {[28, 33],28}, + * {[34, 43],34}, {[44, 51],44}, {[52, 55],52}, + * {[56, 59],56}, {[60, 65],60}, {[66, 71],66}, + * {[72, 79],72}, {[80, 84],80}}. + */ + + if (power < 8 || power > 84) + { + wlerr("Failed to set transmit power =%d\n", power); + return -ENOSYS; + } + + esp_wifi_set_max_tx_power(power); + return OK; + } + else + { + ret = esp_wifi_get_max_tx_power(&power); + if (ret) + { + wlerr("Failed to get transmit power ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + iwr->u.txpower.disabled = 0; + iwr->u.txpower.flags = IW_TXPOW_DBM; + iwr->u.txpower.value = power / 4; + } + + return OK; +} + +/**************************************************************************** + * Name: esp_wifi_sta_channel + * + * Description: + * Get station range of channel parameters. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_channel(struct iwreq *iwr, bool set) +{ + int ret; + int k; + wifi_country_t country; + struct iw_range *range; + + if (set) + { + return -ENOSYS; + } + else + { + ret = esp_wifi_get_country(&country); + if (ret) + { + wlerr("Failed to get country info ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + range = (struct iw_range *)iwr->u.data.pointer; + range->num_frequency = country.nchan; + for (k = 1; k <= range->num_frequency; k++) + { + range->freq[k - 1].i = k; + range->freq[k - 1].e = 0; + range->freq[k - 1].m = 2407 + 5 * k; + } + } + + return OK; +} + +/**************************************************************************** + * Name: esp_wifi_sta_country + * + * Description: + * Configure country info. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_country(struct iwreq *iwr, bool set) +{ + int ret; + char *country_code; + wifi_country_t country; + + if (set) + { + memset(&country, 0x00, sizeof(wifi_country_t)); + country.schan = 1; + country.policy = 0; + + country_code = (char *)iwr->u.data.pointer; + if (strlen(country_code) != 2) + { + wlerr("Invalid input arguments\n"); + return -EINVAL; + } + + if (strncmp(country_code, "US", 3) == 0 || + strncmp(country_code, "CA", 3) == 0) + { + country.nchan = 11; + } + else if(strncmp(country_code, "JP", 3) == 0) + { + country.nchan = 14; + } + else + { + country.nchan = 13; + } + + memcpy(country.cc, country_code, 2); + ret = esp_wifi_set_country(&country); + if (ret) + { + wlerr("Failed to Configure country ret=%d\n", ret); + return wifi_errno_trans(ret); + } + } + else + { + return -ENOSYS; + } + + return OK; +} + +#ifdef ESPRESSIF_WLAN_HAS_STA + +/**************************************************************************** + * Name: esp_wifi_sta_rssi + * + * Description: + * Get Wi-Fi sensitivity (dBm). + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_rssi(struct iwreq *iwr, bool set) +{ + int ret; + wifi_ap_record_t ap_info; + + if (set) + { + return -ENOSYS; + } + else + { + if (g_sta_connected == false) + { + iwr->u.sens.value = 128; + return OK; + } + + ret = esp_wifi_sta_get_ap_info(&ap_info); + if (ret) + { + wlerr("Failed to get AP record ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + iwr->u.sens.value = -(ap_info.rssi); + } + + return OK; +} +#endif /* ESPRESSIF_WLAN_HAS_STA */ + +/**************************************************************************** + * SoftAP functions + ****************************************************************************/ + +#ifdef ESPRESSIF_WLAN_HAS_SOFTAP + +/**************************************************************************** + * Name: esp_wifi_softap_start + * + * Description: + * Start Wi-Fi SoftAP. + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_start(void) +{ + int ret; + wifi_mode_t mode; + + esp_wifi_lock(true); + + ret = esp_wifi_stop(); + if (ret) + { + wlinfo("Failed to stop Wi-Fi ret=%d\n", ret); + } + +#ifdef ESPRESSIF_WLAN_HAS_STA + if (g_sta_started) + { + mode = WIFI_MODE_APSTA; + } + else +#endif /* ESPRESSIF_WLAN_HAS_STA */ + { + mode = WIFI_MODE_AP; + } + + ret = esp_wifi_set_mode(mode); + if (ret) + { + wlerr("Failed to set Wi-Fi mode=%d ret=%d\n", mode, ret); + ret = wifi_errno_trans(ret); + goto errout; + } + + ret = esp_wifi_start(); + if (ret) + { + wlerr("Failed to start Wi-Fi with mode=%d ret=%d\n", mode, ret); + ret = wifi_errno_trans(ret); + goto errout; + } + + g_softap_started = true; + + wlinfo("OK to start Wi-Fi SoftAP\n"); + +errout: + esp_wifi_lock(false); + return ret; +} + +/**************************************************************************** + * Name: esp_wifi_softap_stop + * + * Description: + * Stop Wi-Fi SoftAP. + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_stop(void) +{ + int ret; + + esp_wifi_lock(true); + + ret = esp_wifi_stop(); + if (ret) + { + wlinfo("Failed to stop Wi-Fi ret=%d\n", ret); + } + + g_softap_started = false; + +#ifdef ESPRESSIF_WLAN_HAS_STA + if (g_sta_started) + { + ret = esp_wifi_set_mode(WIFI_MODE_STA); + if (ret) + { + wlerr("Failed to set Wi-Fi AP mode ret=%d\n", ret); + ret = wifi_errno_trans(ret); + goto errout; + } + + ret = esp_wifi_start(); + if (ret) + { + wlerr("Failed to start Wi-Fi STA ret=%d\n", ret); + ret = wifi_errno_trans(ret); + goto errout; + } + } +#endif /* ESPRESSIF_WLAN_HAS_STA */ + + wlinfo("OK to stop Wi-Fi SoftAP\n"); + +#ifdef ESPRESSIF_WLAN_HAS_STA +errout: +#endif /* ESPRESSIF_WLAN_HAS_STA */ + + esp_wifi_lock(false); + return ret; +} + +/**************************************************************************** + * Name: esp_wifi_softap_send_data + * + * Description: + * Use Wi-Fi SoftAP interface to send 802.3 frame + * + * Input Parameters: + * pbuf - Packet buffer pointer + * len - Packet length + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_send_data(void *pbuf, size_t len) +{ + int ret; + + ret = esp_wifi_internal_tx(WIFI_IF_AP, pbuf, len); + + return wifi_errno_trans(ret); +} + +/**************************************************************************** + * Name: esp_wifi_softap_register_recv_cb + * + * Description: + * Register Wi-Fi SoftAP receive packet callback function + * + * Input Parameters: + * recv_cb - Receive callback function + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_register_recv_cb(int (*recv_cb)(void *buffer, + uint16_t len, + void *eb)) +{ + int ret; + + ret = esp_wifi_internal_reg_rxcb(ESP_IF_WIFI_AP, (wifi_rxcb_t)recv_cb); + + return wifi_errno_trans(ret); +} + +/**************************************************************************** + * Name: esp_wifi_softap_register_txdone_cb + * + * Description: + * Register the SoftAP TX done callback function. + * + * Input Parameters: + * cb - The callback function + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp_wifi_softap_register_txdone_cb(wifi_txdone_cb_t cb) +{ + g_softap_txdone_cb = cb; +} + +/**************************************************************************** + * Name: esp_wifi_softap_read_mac + * + * Description: + * Read SoftAP interface MAC address from efuse + * + * Input Parameters: + * mac - MAC address buffer pointer + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_softap_read_mac(uint8_t *mac) +{ + return esp_read_mac(mac, ESP_MAC_WIFI_SOFTAP); +} + +/**************************************************************************** + * Name: esp_wifi_softap_password + * + * Description: + * Set/Get Wi-Fi SoftAP password + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_password(struct iwreq *iwr, bool set) +{ + int ret; + int size; + wifi_config_t wifi_cfg; + struct iw_encode_ext *ext = iwr->u.encoding.pointer; + uint8_t *pdata; + uint8_t len; +#ifdef CONFIG_DEBUG_WIRELESS_INFO + char buf[PWD_MAX_LEN + 1]; +#endif + + DEBUGASSERT(ext != NULL); + + pdata = ext->key; + len = ext->key_len; + + if (set && len > PWD_MAX_LEN) + { + return -EINVAL; + } + + pdata = ext->key; + len = ext->key_len; + + wifi_cfg = g_softap_wifi_cfg; + + if (set) + { + /* Clear the password field and copy the user password to it */ + + memset(wifi_cfg.ap.password, 0x0, PWD_MAX_LEN); + + if (ext->alg != IW_ENCODE_ALG_NONE) + { + memcpy(wifi_cfg.sta.password, pdata, len); + } + + if (g_softap_started) + { + ret = esp_wifi_set_config(WIFI_IF_AP, &wifi_cfg); + if (ret) + { + wlerr("Failed to set Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + } + + g_softap_wifi_cfg = wifi_cfg; + } + else + { + size = strnlen((char *)wifi_cfg.ap.password, PWD_MAX_LEN); + if (len < size) + { + return -EINVAL; + } + else + { + len = size; + memcpy(pdata, wifi_cfg.ap.password, len); + } + } + +#ifdef CONFIG_DEBUG_WIRELESS_INFO + memcpy(buf, pdata, len); + buf[len] = 0; + wlinfo("Wi-Fi SoftAP password=%s len=%d\n", buf, len); +#endif + + return OK; +} + +/**************************************************************************** + * Name: esp_wifi_softap_essid + * + * Description: + * Set/Get Wi-Fi SoftAP ESSID + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_essid(struct iwreq *iwr, bool set) +{ + int ret; + int size; + wifi_config_t wifi_cfg; + struct iw_point *essid = &iwr->u.essid; + uint8_t *pdata; + uint8_t len; +#ifdef CONFIG_DEBUG_WIRELESS_INFO + char buf[SSID_MAX_LEN + 1]; +#endif + + DEBUGASSERT(essid != NULL); + + pdata = essid->pointer; + len = essid->length; + + if (set && len > SSID_MAX_LEN) + { + return -EINVAL; + } + + wifi_cfg = g_softap_wifi_cfg; + + if (set) + { + memset(wifi_cfg.ap.ssid, 0x0, SSID_MAX_LEN); + memcpy(wifi_cfg.ap.ssid, pdata, len); + wifi_cfg.ap.ssid_len = len; + if (g_softap_started) + { + ret = esp_wifi_set_config(WIFI_IF_AP, &wifi_cfg); + if (ret) + { + wlerr("Failed to set Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + } + + g_softap_wifi_cfg = wifi_cfg; + } + else + { + size = strnlen((char *)wifi_cfg.ap.ssid, SSID_MAX_LEN); + if (len < size) + { + return -EINVAL; + } + else + { + len = size; + memcpy(pdata, wifi_cfg.ap.ssid, len); + } + } + +#ifdef CONFIG_DEBUG_WIRELESS_INFO + memcpy(buf, pdata, len); + buf[len] = 0; + wlinfo("Wi-Fi SoftAP ssid=%s len=%d\n", buf, len); +#endif + + return OK; +} + +/**************************************************************************** + * Name: esp_wifi_softap_bssid + * + * Description: + * Set/Get Wi-Fi softAP BSSID + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_bssid(struct iwreq *iwr, bool set) +{ + return -ENOSYS; +} + +/**************************************************************************** + * Name: esp_wifi_softap_connect + * + * Description: + * Trigger Wi-Fi SoftAP accept connection action + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_connect(void) +{ + int ret; + + ret = esp_wifi_set_config(WIFI_IF_AP, &g_softap_wifi_cfg); + if (ret) + { + wlerr("Failed to set Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + return OK; +} + +/**************************************************************************** + * Name: esp_wifi_softap_disconnect + * + * Description: + * Trigger Wi-Fi SoftAP drop connection action + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_disconnect(void) +{ + return OK; +} + +/**************************************************************************** + * Name: esp_wifi_softap_mode + * + * Description: + * Set/Get Wi-Fi SoftAP mode code. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_mode(struct iwreq *iwr, bool set) +{ + if (set == false) + { + iwr->u.mode = IW_MODE_MASTER; + } + + return OK; +} + +/**************************************************************************** + * Name: esp_wifi_softap_auth + * + * Description: + * Set/get authentication mode params. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_auth(struct iwreq *iwr, bool set) +{ + int ret; + int cmd; + wifi_config_t wifi_cfg; + + wifi_cfg = g_softap_wifi_cfg; + + if (set) + { + cmd = iwr->u.param.flags & IW_AUTH_INDEX; + switch (cmd) + { + case IW_AUTH_WPA_VERSION: + { + switch (iwr->u.param.value) + { + case IW_AUTH_WPA_VERSION_DISABLED: + wifi_cfg.ap.authmode = WIFI_AUTH_OPEN; + break; + + case IW_AUTH_WPA_VERSION_WPA: + wifi_cfg.ap.authmode = WIFI_AUTH_WPA_PSK; + break; + + case IW_AUTH_WPA_VERSION_WPA2: + wifi_cfg.ap.authmode = WIFI_AUTH_WPA2_PSK; + break; + + case IW_AUTH_WPA_VERSION_WPA3: + wifi_cfg.ap.pmf_cfg.required = true; + wifi_cfg.ap.pmf_cfg.capable = false; + wifi_cfg.ap.sae_pwe_h2e = WPA3_SAE_PWE_BOTH; + wifi_cfg.ap.authmode = WIFI_AUTH_WPA3_PSK; + break; + + default: + wlerr("Invalid wpa version %" PRId32 "\n", + iwr->u.param.value); + return -EINVAL; + } + } + + break; + case IW_AUTH_CIPHER_PAIRWISE: + case IW_AUTH_CIPHER_GROUP: + { + switch (iwr->u.param.value) + { + case IW_AUTH_CIPHER_NONE: + wifi_cfg.ap.authmode = WIFI_AUTH_OPEN; + break; + + case IW_AUTH_CIPHER_WEP40: + case IW_AUTH_CIPHER_WEP104: + wifi_cfg.ap.authmode = WIFI_AUTH_WEP; + break; + + case IW_AUTH_CIPHER_TKIP: + case IW_AUTH_CIPHER_CCMP: + case IW_AUTH_CIPHER_AES_CMAC: + break; + + default: + wlerr("Invalid cipher mode %" PRId32 "\n", + iwr->u.param.value); + return -EINVAL; + } + } + + break; + case IW_AUTH_KEY_MGMT: + case IW_AUTH_TKIP_COUNTERMEASURES: + case IW_AUTH_DROP_UNENCRYPTED: + case IW_AUTH_80211_AUTH_ALG: + case IW_AUTH_WPA_ENABLED: + case IW_AUTH_RX_UNENCRYPTED_EAPOL: + case IW_AUTH_ROAMING_CONTROL: + case IW_AUTH_PRIVACY_INVOKED: + default: + wlerr("Unknown cmd %d\n", cmd); + return -EINVAL; + } + + size_t password_len = strlen((const char *)wifi_cfg.ap.password); + + if (g_softap_started && + ((password_len > 0 && wifi_cfg.ap.authmode != WIFI_AUTH_OPEN) || + (password_len == 0 && wifi_cfg.ap.authmode == WIFI_AUTH_OPEN))) + { + ret = esp_wifi_set_config(WIFI_IF_AP, &wifi_cfg); + if (ret) + { + wlerr("Failed to set Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + } + + g_softap_wifi_cfg = wifi_cfg; + } + else + { + return -ENOSYS; + } + + return OK; +} + +/**************************************************************************** + * Name: esp_wifi_softap_freq + * + * Description: + * Set/Get SoftAP frequency. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_freq(struct iwreq *iwr, bool set) +{ + int ret; + wifi_config_t wifi_cfg; + + wifi_cfg = g_softap_wifi_cfg; + + if (set) + { + int channel = esp_freq_to_channel(iwr->u.freq.m); + + wifi_cfg.ap.channel = channel; + + if (g_softap_started) + { + ret = esp_wifi_set_config(WIFI_IF_AP, &wifi_cfg); + if (ret) + { + wlerr("Failed to set Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + } + + g_softap_wifi_cfg = wifi_cfg; + } + else + { + iwr->u.freq.flags = IW_FREQ_FIXED; + iwr->u.freq.e = 0; + iwr->u.freq.m = 2407 + 5 * wifi_cfg.ap.channel; + } + + return OK; +} + +/**************************************************************************** + * Name: esp_wifi_softap_get_bitrate + * + * Description: + * Get SoftAP default bit rate (Mbps). + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_bitrate(struct iwreq *iwr, bool set) +{ + return -ENOSYS; +} + +/**************************************************************************** + * Name: esp_wifi_softap_txpower + * + * Description: + * Get SoftAP transmit power (dBm). + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_txpower(struct iwreq *iwr, bool set) +{ + return esp_wifi_sta_txpower(iwr, set); +} + +/**************************************************************************** + * Name: esp_wifi_softap_channel + * + * Description: + * Get SoftAP range of channel parameters. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_channel(struct iwreq *iwr, bool set) +{ + return esp_wifi_sta_channel(iwr, set); +} + +/**************************************************************************** + * Name: esp_wifi_softap_country + * + * Description: + * Configure country info. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_country(struct iwreq *iwr, bool set) +{ + return esp_wifi_sta_country(iwr, set); +} + +/**************************************************************************** + * Name: esp_wifi_softap_rssi + * + * Description: + * Get Wi-Fi sensitivity (dBm). + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_rssi(struct iwreq *iwr, bool set) +{ + return -ENOSYS; +} + +#endif /* ESPRESSIF_WLAN_HAS_SOFTAP */ + +/**************************************************************************** + * Name: esp_wifi_stop_callback + * + * Description: + * Callback to stop Wi-Fi + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp_wifi_stop_callback(void) +{ + wlinfo("INFO: Try to stop Wi-Fi\n"); + + int ret = esp_wifi_stop(); + if (ret) + { + wlerr("ERROR: Failed to stop Wi-Fi ret=%d\n", ret); + } + else + { + nxsig_sleep(1); + } +} diff --git a/arch/xtensa/src/esp32s2/esp32s2_wifi_adapter.h b/arch/xtensa/src/esp32s2/esp32s2_wifi_adapter.h new file mode 100644 index 00000000000..109740eed62 --- /dev/null +++ b/arch/xtensa/src/esp32s2/esp32s2_wifi_adapter.h @@ -0,0 +1,849 @@ +/**************************************************************************** + * arch/xtensa/src/esp32s2/esp32s2_wifi_adapter.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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 __ARCH_XTENSA_SRC_ESP32S2_ESP32S2_WIFI_ADAPTER_H +#define __ARCH_XTENSA_SRC_ESP32S2_ESP32S2_WIFI_ADAPTER_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#if defined(CONFIG_ESPRESSIF_WIFI_STATION) +# define ESPRESSIF_WLAN_HAS_STA +# define ESPRESSIF_WLAN_STA_DEVNO 0 +# define ESPRESSIF_WLAN_DEVS 1 +#elif defined(CONFIG_ESPRESSIF_WIFI_SOFTAP) +# define ESPRESSIF_WLAN_HAS_SOFTAP +# define ESPRESSIF_WLAN_SOFTAP_DEVNO 0 +# define ESPRESSIF_WLAN_DEVS 1 +#elif defined(CONFIG_ESPRESSIF_WIFI_STATION_SOFTAP) +# define ESPRESSIF_WLAN_HAS_STA +# define ESPRESSIF_WLAN_HAS_SOFTAP +# define ESPRESSIF_WLAN_STA_DEVNO 0 +# define ESPRESSIF_WLAN_SOFTAP_DEVNO 1 +# define ESPRESSIF_WLAN_DEVS 2 +#endif + +#define SSID_MAX_LEN (32) +#define PWD_MAX_LEN (64) + +#define CONFIG_IDF_TARGET_ESP32S2 1 + +/* Define esp_err_t */ + +typedef int esp_err_t; + +/* Wi-Fi event ID */ + +enum wifi_adpt_evt_e +{ + WIFI_ADPT_EVT_SCAN_DONE = 0, + WIFI_ADPT_EVT_STA_START, + WIFI_ADPT_EVT_STA_CONNECT, + WIFI_ADPT_EVT_STA_DISCONNECT, + WIFI_ADPT_EVT_STA_AUTHMODE_CHANGE, + WIFI_ADPT_EVT_STA_STOP, + WIFI_ADPT_EVT_AP_START, + WIFI_ADPT_EVT_AP_STOP, + WIFI_ADPT_EVT_AP_STACONNECTED, + WIFI_ADPT_EVT_AP_STADISCONNECTED, + WIFI_ADPT_EVT_MAX, +}; + +/* Wi-Fi event callback function */ + +typedef void (*wifi_evt_cb_t)(void *p); + +/* Wi-Fi TX done callback function */ + +typedef void (*wifi_txdone_cb_t)(uint8_t *data, uint16_t *len, bool status); + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: esp_wifi_adapter_init + * + * Description: + * Initialize ESP32S2 Wi-Fi adapter + * + * Input Parameters: + * None + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_adapter_init(void); + +/**************************************************************************** + * Name: esp_wifi_free_eb + * + * Description: + * Free Wi-Fi receive callback input eb pointer + * + * Input Parameters: + * eb - Wi-Fi receive callback input eb pointer + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp_wifi_free_eb(void *eb); + +/**************************************************************************** + * Name: esp_wifi_notify_subscribe + * + * Description: + * Enable event notification + * + * Input Parameters: + * pid - Task PID + * event - Signal event data pointer + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_notify_subscribe(pid_t pid, struct sigevent *event); + +#ifdef ESPRESSIF_WLAN_HAS_STA + +/**************************************************************************** + * Name: esp_wifi_sta_start + * + * Description: + * Start Wi-Fi station. + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_start(void); + +/**************************************************************************** + * Name: esp_wifi_sta_stop + * + * Description: + * Stop Wi-Fi station. + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_stop(void); + +/**************************************************************************** + * Name: esp_wifi_sta_send_data + * + * Description: + * Use Wi-Fi station interface to send 802.3 frame + * + * Input Parameters: + * pbuf - Packet buffer pointer + * len - Packet length + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_send_data(void *pbuf, uint32_t len); + +/**************************************************************************** + * Name: esp_wifi_sta_register_recv_cb + * + * Description: + * Regitser Wi-Fi station receive packet callback function + * + * Input Parameters: + * recv_cb - Receive callback function + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_register_recv_cb(int (*recv_cb)(void *buffer, + uint16_t len, + void *eb)); + +/**************************************************************************** + * Name: esp_wifi_sta_register_txdone_cb + * + * Description: + * Register the station TX done callback function. + * + * Input Parameters: + * cb - The callback function + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp_wifi_sta_register_txdone_cb(wifi_txdone_cb_t cb); + +/**************************************************************************** + * Name: esp_wifi_sta_read_mac + * + * Description: + * Read station interface MAC address from efuse + * + * Input Parameters: + * mac - MAC address buffer pointer + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_sta_read_mac(uint8_t *mac); + +/**************************************************************************** + * Name: esp_wifi_set_password + * + * Description: + * Set/Get Wi-Fi station password + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_password(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_sta_essid + * + * Description: + * Set/Get Wi-Fi station ESSID + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_essid(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_sta_bssid + * + * Description: + * Set/Get Wi-Fi station BSSID + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_bssid(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_sta_connect + * + * Description: + * Trigger Wi-Fi station connection action + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_connect(void); + +/**************************************************************************** + * Name: esp_wifi_sta_disconnect + * + * Description: + * Trigger Wi-Fi station disconnection action + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_disconnect(void); + +/**************************************************************************** + * Name: esp_wifi_sta_mode + * + * Description: + * Set/Get Wi-Fi Station mode code. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_mode(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_sta_auth + * + * Description: + * Set/Get station authentication mode params. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_auth(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_sta_freq + * + * Description: + * Get station frequency. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_freq(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_sta_bitrate + * + * Description: + * Get station default bit rate (Mbps). + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_bitrate(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_sta_get_txpower + * + * Description: + * Get station transmit power (dBm). + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_txpower(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_sta_get_channel_range + * + * Description: + * Get station range of channel parameters. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_channel(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_sta_country + * + * Description: + * Configure country info. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_country(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_sta_rssi + * + * Description: + * Get Wi-Fi sensitivity (dBm). + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_sta_rssi(struct iwreq *iwr, bool set); +#endif /* ESPRESSIF_WLAN_HAS_STA */ + +#ifdef ESPRESSIF_WLAN_HAS_SOFTAP + +/**************************************************************************** + * Name: esp_wifi_softap_start + * + * Description: + * Start Wi-Fi softAP. + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_start(void); + +/**************************************************************************** + * Name: esp_wifi_softap_stop + * + * Description: + * Stop Wi-Fi softAP. + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_stop(void); + +/**************************************************************************** + * Name: esp_wifi_softap_send_data + * + * Description: + * Use Wi-Fi softAP interface to send 802.3 frame + * + * Input Parameters: + * pbuf - Packet buffer pointer + * len - Packet length + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_send_data(void *pbuf, size_t len); + +/**************************************************************************** + * Name: esp_wifi_softap_register_recv_cb + * + * Description: + * Regitser Wi-Fi softAP receive packet callback function + * + * Input Parameters: + * recv_cb - Receive callback function + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_register_recv_cb(int (*recv_cb)(void *buffer, + uint16_t len, + void *eb)); + +/**************************************************************************** + * Name: esp_wifi_softap_register_txdone_cb + * + * Description: + * Register the softAP TX done callback function. + * + * Input Parameters: + * cb - The callback function + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp_wifi_softap_register_txdone_cb(wifi_txdone_cb_t cb); + +/**************************************************************************** + * Name: esp_wifi_softap_read_mac + * + * Description: + * Read softAP interface MAC address from efuse + * + * Input Parameters: + * mac - MAC address buffer pointer + * + * Returned Value: + * 0 if success or -1 if fail + * + ****************************************************************************/ + +int esp_wifi_softap_read_mac(uint8_t *mac); + +/**************************************************************************** + * Name: esp_wifi_softap_password + * + * Description: + * Set/Get Wi-Fi SoftAP password + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_password(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_softap_essid + * + * Description: + * Set/Get Wi-Fi SoftAP ESSID + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_essid(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_softap_bssid + * + * Description: + * Set/Get Wi-Fi softAP BSSID + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_bssid(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_softap_connect + * + * Description: + * Trigger Wi-Fi softAP accept connection action + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_connect(void); + +/**************************************************************************** + * Name: esp_wifi_softap_disconnect + * + * Description: + * Trigger Wi-Fi softAP drop connection action + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_disconnect(void); + +/**************************************************************************** + * Name: esp_wifi_softap_mode + * + * Description: + * Set/Get Wi-Fi SoftAP mode code. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_mode(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_softap_auth + * + * Description: + * Set/Get authentication mode params. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_auth(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_softap_freq + * + * Description: + * Set/Get SoftAP frequency. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_freq(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_softap_get_bitrate + * + * Description: + * Get SoftAP default bit rate (Mbps). + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_bitrate(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_softap_txpower + * + * Description: + * Get SoftAP transmit power (dBm). + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_txpower(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_softap_channel + * + * Description: + * Get SoftAP range of channel parameters. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_channel(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_softap_country + * + * Description: + * Configure country info. + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_country(struct iwreq *iwr, bool set); + +/**************************************************************************** + * Name: esp_wifi_softap_rssi + * + * Description: + * Get Wi-Fi sensitivity (dBm). + * + * Input Parameters: + * iwr - The argument of the ioctl cmd + * set - true: set data; false: get data + * + * Returned Value: + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. + * + ****************************************************************************/ + +int esp_wifi_softap_rssi(struct iwreq *iwr, bool set); +#endif /* ESPRESSIF_WLAN_HAS_SOFTAP */ + +/**************************************************************************** + * Name: esp_wifi_stop_callback + * + * Description: + * Callback to stop Wi-Fi + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp_wifi_stop_callback(void); + +#ifdef __cplusplus +} +#endif +#undef EXTERN + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_XTENSA_SRC_ESP32S2_ESP32S2_WIFI_ADAPTER_H */ diff --git a/arch/xtensa/src/esp32s2/hal.mk b/arch/xtensa/src/esp32s2/hal.mk index e5336f6be9b..630997e2eeb 100644 --- a/arch/xtensa/src/esp32s2/hal.mk +++ b/arch/xtensa/src/esp32s2/hal.mk @@ -28,12 +28,15 @@ INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)efuse$(DELIM)$(CHIP_SERIES)$(DELIM)include INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)efuse$(DELIM)$(CHIP_SERIES)$(DELIM)private_include INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_common$(DELIM)include +INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_event$(DELIM)include INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hw_support$(DELIM)include INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hw_support$(DELIM)include$(DELIM)esp_private INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hw_support$(DELIM)include$(DELIM)soc INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hw_support$(DELIM)port$(DELIM)$(CHIP_SERIES) INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hw_support$(DELIM)port$(DELIM)$(CHIP_SERIES)$(DELIM)private_include INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hw_support$(DELIM)port$(DELIM)include +INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_phy$(DELIM)$(CHIP_SERIES)$(DELIM)include +INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_phy$(DELIM)include INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_rom$(DELIM)$(CHIP_SERIES) INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_rom$(DELIM)include INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_rom$(DELIM)include$(DELIM)$(CHIP_SERIES) @@ -42,6 +45,7 @@ INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_system$(DELIM)port$(DELIM)include$(DELIM)private INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_system$(DELIM)port$(DELIM)public_compat INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_timer$(DELIM)include +INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_wifi$(DELIM)include INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)$(CHIP_SERIES)$(DELIM)include INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)include INCLUDES += $(INCDIR_PREFIX)$(ARCH_SRCDIR)$(DELIM)chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)platform_port$(DELIM)include @@ -75,6 +79,7 @@ CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_ CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hw_support$(DELIM)cpu.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hw_support$(DELIM)esp_clk.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hw_support$(DELIM)hw_random.c +CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hw_support$(DELIM)mac_addr.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hw_support$(DELIM)periph_ctrl.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hw_support$(DELIM)port$(DELIM)$(CHIP_SERIES)$(DELIM)cpu_region_protect.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hw_support$(DELIM)port$(DELIM)$(CHIP_SERIES)$(DELIM)esp_clk_tree.c @@ -83,6 +88,8 @@ CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_ CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hw_support$(DELIM)port$(DELIM)$(CHIP_SERIES)$(DELIM)rtc_time.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hw_support$(DELIM)port$(DELIM)esp_clk_tree_common.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hw_support$(DELIM)regi2c_ctrl.c +CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_phy$(DELIM)src$(DELIM)phy_init.c +CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_phy$(DELIM)src$(DELIM)phy_common.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_rom$(DELIM)patches$(DELIM)esp_rom_regi2c_$(CHIP_SERIES).c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_rom$(DELIM)patches$(DELIM)esp_rom_wdt.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_system$(DELIM)port$(DELIM)soc$(DELIM)$(CHIP_SERIES)$(DELIM)clk.c @@ -110,6 +117,10 @@ CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)soc$ CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)soc$(DELIM)$(CHIP_SERIES)$(DELIM)temperature_sensor_periph.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)spi_flash$(DELIM)flash_ops.c +# Bootloader files +CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)bootloader_support$(DELIM)src$(DELIM)${CHIP_SERIES}$(DELIM)bootloader_soc.c +CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)bootloader_support$(DELIM)src$(DELIM)bootloader_random_${CHIP_SERIES}.c + ifeq ($(CONFIG_ESPRESSIF_SIMPLE_BOOT),y) CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)nuttx$(DELIM)src$(DELIM)bootloader_banner_wrap.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)bootloader_support$(DELIM)src$(DELIM)bootloader_console.c @@ -125,9 +136,7 @@ ifeq ($(CONFIG_ESPRESSIF_SIMPLE_BOOT),y) CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)bootloader_support$(DELIM)src$(DELIM)bootloader_efuse.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)bootloader_support$(DELIM)src$(DELIM)bootloader_mem.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)bootloader_support$(DELIM)src$(DELIM)bootloader_random.c - CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)bootloader_support$(DELIM)src$(DELIM)bootloader_random_${CHIP_SERIES}.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)bootloader_support$(DELIM)src$(DELIM)esp_image_format.c - CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)bootloader_support$(DELIM)src$(DELIM)${CHIP_SERIES}$(DELIM)bootloader_soc.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)bootloader_support$(DELIM)src$(DELIM)${CHIP_SERIES}$(DELIM)bootloader_sha.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)bootloader_support$(DELIM)src$(DELIM)flash_encrypt.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)soc$(DELIM)${CHIP_SERIES}$(DELIM)uart_periph.c diff --git a/boards/xtensa/esp32s2/common/include/esp32s2_board_wlan.h b/boards/xtensa/esp32s2/common/include/esp32s2_board_wlan.h new file mode 100644 index 00000000000..2eb2546f2bf --- /dev/null +++ b/boards/xtensa/esp32s2/common/include/esp32s2_board_wlan.h @@ -0,0 +1,73 @@ +/**************************************************************************** + * boards/xtensa/esp32s2/common/include/esp32s2_board_wlan.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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 __BOARDS_XTENSA_ESP32S2_COMMON_INCLUDE_ESP32S2_BOARD_WLAN_H +#define __BOARDS_XTENSA_ESP32S2_COMMON_INCLUDE_ESP32S2_BOARD_WLAN_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef CONFIG_ESPRESSIF_WIFI + +/**************************************************************************** + * Name: board_wlan_init + * + * Description: + * Configure the wireless subsystem. + * + * Returned Value: + * Zero (OK) is returned on success; A negated errno value is returned + * to indicate the nature of any failure. + * + ****************************************************************************/ + +int board_wlan_init(void); + +#endif /* CONFIG_ESPRESSIF_WIFI */ + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __BOARDS_XTENSA_ESP32S2_COMMON_INCLUDE_ESP32S2_BOARD_WLAN_H */ diff --git a/boards/xtensa/esp32s2/common/scripts/simple_boot_sections.ld b/boards/xtensa/esp32s2/common/scripts/simple_boot_sections.ld index dc55f76dc6b..1d5ad95394c 100644 --- a/boards/xtensa/esp32s2/common/scripts/simple_boot_sections.ld +++ b/boards/xtensa/esp32s2/common/scripts/simple_boot_sections.ld @@ -18,6 +18,8 @@ * ****************************************************************************/ +#include + /* Default entry point: */ ENTRY(__start); @@ -134,6 +136,13 @@ SECTIONS *libarch.a:*cpu_region_protect.*(.text .text.* .literal .literal.*) *libc.a:sq_remlast.*(.literal .text .literal.* .text.*) + *(.wifirxiram .wifirxiram.*) + *(.wifi0iram .wifi0iram.*) + *(.wifiorslpiram .wifiorslpiram.*) + *(.wifislpiram .wifislpiram.*) + *(.wifislprxiram .wifislprxiram.*) + *(.phyiram .phyiram.*) + *(.wifiextrairam .wifiextrairam.*) /* align + add 16B for CPU dummy speculative instr. fetch */ @@ -312,6 +321,14 @@ SECTIONS *(.rodata) *(.rodata.*) +#ifdef CONFIG_ESPRESSIF_WIRELESS + *(.rodata_wlog_verbose.*) + *(.rodata_wlog_debug.*) + *(.rodata_wlog_info.*) + *(.rodata_wlog_warning.*) + *(.rodata_wlog_error.*) +#endif + *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ *(.gnu.linkonce.r.*) *(.rodata1) @@ -419,6 +436,7 @@ SECTIONS .rtc.data : { + . = ALIGN(4); *(.rtc.data) *(.rtc.data.*) *(.rtc.rodata) diff --git a/boards/xtensa/esp32s2/common/src/Make.defs b/boards/xtensa/esp32s2/common/src/Make.defs index 7a8c29bd8dd..95f20658d58 100644 --- a/boards/xtensa/esp32s2/common/src/Make.defs +++ b/boards/xtensa/esp32s2/common/src/Make.defs @@ -32,6 +32,10 @@ ifeq ($(CONFIG_SPI_DRIVER),y) CSRCS += esp32s2_board_spidev.c endif +ifeq ($(CONFIG_ESPRESSIF_WIFI),y) + CSRCS += esp32s2_board_wlan.c +endif + ifeq ($(CONFIG_SPI_SLAVE_DRIVER),y) CSRCS += esp32s2_board_spislavedev.c endif diff --git a/boards/xtensa/esp32s2/common/src/esp32s2_board_wlan.c b/boards/xtensa/esp32s2/common/src/esp32s2_board_wlan.c new file mode 100644 index 00000000000..aedb4f839d1 --- /dev/null +++ b/boards/xtensa/esp32s2/common/src/esp32s2_board_wlan.c @@ -0,0 +1,80 @@ +/**************************************************************************** + * boards/xtensa/esp32s2/common/src/esp32s2_board_wlan.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "espressif/esp_wlan.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_wlan_init + * + * Description: + * Configure the wireless subsystem. + * + * Input Parameters: + * None. + * + * Returned Value: + * Zero (OK) is returned on success; A negated errno value is returned + * to indicate the nature of any failure. + * + ****************************************************************************/ + +int board_wlan_init(void) +{ + int ret = OK; + +#ifdef ESPRESSIF_WLAN_HAS_STA + ret = esp_wlan_sta_initialize(); + if (ret) + { + wlerr("ERROR: Failed to initialize Wi-Fi station\n"); + return ret; + } +#endif /* ESPRESSIF_WLAN_HAS_STA */ + +#ifdef ESPRESSIF_WLAN_HAS_SOFTAP + ret = esp_wlan_softap_initialize(); + if (ret) + { + wlerr("ERROR: Failed to initialize Wi-Fi softAP\n"); + return ret; + } +#endif /* ESPRESSIF_WLAN_HAS_SOFTAP */ + + return ret; +} diff --git a/boards/xtensa/esp32s2/esp32s2-saola-1/configs/sta_softap/defconfig b/boards/xtensa/esp32s2/esp32s2-saola-1/configs/sta_softap/defconfig new file mode 100644 index 00000000000..2be4b02210f --- /dev/null +++ b/boards/xtensa/esp32s2/esp32s2-saola-1/configs/sta_softap/defconfig @@ -0,0 +1,86 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_LEDS is not set +# CONFIG_NSH_ARGCAT is not set +# CONFIG_NSH_CMDOPT_HEXDUMP is not set +CONFIG_ALLOW_BSD_COMPONENTS=y +CONFIG_ARCH="xtensa" +CONFIG_ARCH_BOARD="esp32s2-saola-1" +CONFIG_ARCH_BOARD_COMMON=y +CONFIG_ARCH_BOARD_ESP32S2_SAOLA_1=y +CONFIG_ARCH_CHIP="esp32s2" +CONFIG_ARCH_CHIP_ESP32S2=y +CONFIG_ARCH_CHIP_ESP32S2WROVER=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARCH_XTENSA=y +CONFIG_BOARD_LOOPSPERMSEC=16717 +CONFIG_BUILTIN=y +CONFIG_DEFAULT_TASK_STACKSIZE=4096 +CONFIG_DRIVERS_IEEE80211=y +CONFIG_DRIVERS_WIRELESS=y +CONFIG_ESP32S2_RT_TIMER_TASK_STACK_SIZE=4096 +CONFIG_ESP32S2_SPIFLASH_SPIFFS=y +CONFIG_ESP32S2_UART0=y +CONFIG_ESPRESSIF_SPIFLASH=y +CONFIG_ESPRESSIF_WIFI=y +CONFIG_ESPRESSIF_WIFI_STATION_SOFTAP=y +CONFIG_EXAMPLES_DHCPD=y +CONFIG_FS_PROCFS=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_IDLETHREAD_STACKSIZE=3072 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INIT_STACKSIZE=8192 +CONFIG_INTELHEX_BINARY=y +CONFIG_IOB_NBUFFERS=124 +CONFIG_IOB_THROTTLE=24 +CONFIG_NAME_MAX=48 +CONFIG_NETDB_DNSCLIENT=y +CONFIG_NETDEV_LATEINIT=y +CONFIG_NETDEV_PHY_IOCTL=y +CONFIG_NETDEV_WIRELESS_IOCTL=y +CONFIG_NETUTILS_CJSON=y +CONFIG_NETUTILS_DHCPD=y +CONFIG_NETUTILS_IPERF=y +CONFIG_NET_BROADCAST=y +CONFIG_NET_ETH_PKTSIZE=1514 +CONFIG_NET_ICMP_SOCKET=y +CONFIG_NET_TCP=y +CONFIG_NET_TCP_DELAYED_ACK=y +CONFIG_NET_TCP_WRITE_BUFFERS=y +CONFIG_NET_UDP=y +CONFIG_NET_UDP_WRITE_BUFFERS=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_LINELEN=64 +CONFIG_NSH_READLINE=y +CONFIG_POSIX_SPAWN_DEFAULT_STACKSIZE=2048 +CONFIG_PREALLOC_TIMERS=4 +CONFIG_PTHREAD_MUTEX_TYPES=y +CONFIG_RAM_SIZE=114688 +CONFIG_RAM_START=0x20000000 +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_LPWORK=y +CONFIG_SCHED_WAITPID=y +CONFIG_SIG_DEFAULT=y +CONFIG_START_DAY=6 +CONFIG_START_MONTH=12 +CONFIG_START_YEAR=2011 +CONFIG_SYSLOG_BUFFER=y +CONFIG_SYSTEM_DHCPC_RENEW=y +CONFIG_SYSTEM_NSH=y +CONFIG_SYSTEM_PING=y +CONFIG_TIMER=y +CONFIG_TLS_TASK_NELEM=4 +CONFIG_UART0_SERIAL_CONSOLE=y +CONFIG_WIRELESS=y +CONFIG_WIRELESS_WAPI=y +CONFIG_WIRELESS_WAPI_CMDTOOL=y +CONFIG_WIRELESS_WAPI_INITCONF=y +CONFIG_WIRELESS_WAPI_STACKSIZE=8192 diff --git a/boards/xtensa/esp32s2/esp32s2-saola-1/configs/wifi/defconfig b/boards/xtensa/esp32s2/esp32s2-saola-1/configs/wifi/defconfig new file mode 100644 index 00000000000..186407d39a6 --- /dev/null +++ b/boards/xtensa/esp32s2/esp32s2-saola-1/configs/wifi/defconfig @@ -0,0 +1,81 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_LEDS is not set +# CONFIG_NSH_ARGCAT is not set +# CONFIG_NSH_CMDOPT_HEXDUMP is not set +CONFIG_ALLOW_BSD_COMPONENTS=y +CONFIG_ARCH="xtensa" +CONFIG_ARCH_BOARD="esp32s2-saola-1" +CONFIG_ARCH_BOARD_COMMON=y +CONFIG_ARCH_BOARD_ESP32S2_SAOLA_1=y +CONFIG_ARCH_CHIP="esp32s2" +CONFIG_ARCH_CHIP_ESP32S2=y +CONFIG_ARCH_CHIP_ESP32S2WROVER=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARCH_XTENSA=y +CONFIG_BOARD_LOOPSPERMSEC=16717 +CONFIG_BUILTIN=y +CONFIG_DEFAULT_TASK_STACKSIZE=4096 +CONFIG_DRIVERS_IEEE80211=y +CONFIG_DRIVERS_WIRELESS=y +CONFIG_ESP32S2_RT_TIMER_TASK_STACK_SIZE=4096 +CONFIG_ESP32S2_UART0=y +CONFIG_ESPRESSIF_WIFI=y +CONFIG_FS_PROCFS=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_IDLETHREAD_STACKSIZE=3072 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INIT_STACKSIZE=8192 +CONFIG_INTELHEX_BINARY=y +CONFIG_IOB_NBUFFERS=124 +CONFIG_IOB_THROTTLE=24 +CONFIG_NAME_MAX=48 +CONFIG_NETDB_DNSCLIENT=y +CONFIG_NETDEV_LATEINIT=y +CONFIG_NETDEV_PHY_IOCTL=y +CONFIG_NETDEV_WIRELESS_IOCTL=y +CONFIG_NETUTILS_CJSON=y +CONFIG_NETUTILS_IPERF=y +CONFIG_NET_BROADCAST=y +CONFIG_NET_ETH_PKTSIZE=1514 +CONFIG_NET_ICMP_SOCKET=y +CONFIG_NET_TCP=y +CONFIG_NET_TCP_DELAYED_ACK=y +CONFIG_NET_TCP_WRITE_BUFFERS=y +CONFIG_NET_UDP=y +CONFIG_NET_UDP_WRITE_BUFFERS=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_LINELEN=64 +CONFIG_NSH_READLINE=y +CONFIG_POSIX_SPAWN_DEFAULT_STACKSIZE=2048 +CONFIG_PREALLOC_TIMERS=4 +CONFIG_PTHREAD_MUTEX_TYPES=y +CONFIG_RAM_SIZE=114688 +CONFIG_RAM_START=0x20000000 +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_LPWORK=y +CONFIG_SCHED_WAITPID=y +CONFIG_SIG_DEFAULT=y +CONFIG_START_DAY=6 +CONFIG_START_MONTH=12 +CONFIG_START_YEAR=2011 +CONFIG_SYSLOG_BUFFER=y +CONFIG_SYSTEM_DHCPC_RENEW=y +CONFIG_SYSTEM_NSH=y +CONFIG_SYSTEM_PING=y +CONFIG_TIMER=y +CONFIG_TLS_TASK_NELEM=4 +CONFIG_UART0_SERIAL_CONSOLE=y +CONFIG_WIRELESS=y +CONFIG_WIRELESS_WAPI=y +CONFIG_WIRELESS_WAPI_CMDTOOL=y +CONFIG_WIRELESS_WAPI_INITCONF=y +CONFIG_WIRELESS_WAPI_STACKSIZE=8192 diff --git a/boards/xtensa/esp32s2/esp32s2-saola-1/src/esp32s2_bringup.c b/boards/xtensa/esp32s2/esp32s2-saola-1/src/esp32s2_bringup.c index e8c200bc8d8..7bb2a535d1e 100644 --- a/boards/xtensa/esp32s2/esp32s2-saola-1/src/esp32s2_bringup.c +++ b/boards/xtensa/esp32s2/esp32s2-saola-1/src/esp32s2_bringup.c @@ -50,6 +50,10 @@ # include "esp32s2_tim_lowerhalf.h" #endif +#ifdef CONFIG_ESPRESSIF_WIFI +# include "esp32s2_board_wlan.h" +#endif + #ifdef CONFIG_ESP32S2_I2C # include "esp32s2_i2c.h" #endif @@ -302,6 +306,19 @@ int esp32s2_bringup(void) } #endif +#ifdef CONFIG_ESPRESSIF_WIRELESS + +#ifdef CONFIG_ESPRESSIF_WIFI + ret = board_wlan_init(); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to initialize wireless subsystem=%d\n", + ret); + } +#endif + +#endif + #ifdef CONFIG_SENSORS_BMP180 /* Try to register BMP180 device in I2C0 */