From 91eb70b5ef85fa81ba5db76966b4dffa243de83f Mon Sep 17 00:00:00 2001 From: chenwen Date: Tue, 23 Mar 2021 19:48:03 +0800 Subject: [PATCH] risc-v/esp32c3: Support ESP32-C3 wireless ioctl cmd --- arch/risc-v/src/esp32c3/Kconfig | 25 +- arch/risc-v/src/esp32c3/Make.defs | 2 +- .../risc-v/src/esp32c3/esp32c3_wifi_adapter.c | 2455 +++++++++++++++-- .../risc-v/src/esp32c3/esp32c3_wifi_adapter.h | 785 +++++- arch/risc-v/src/esp32c3/esp32c3_wifi_utils.c | 523 ++++ arch/risc-v/src/esp32c3/esp32c3_wifi_utils.h | 120 + arch/risc-v/src/esp32c3/esp32c3_wlan.c | 995 +++++-- arch/risc-v/src/esp32c3/esp32c3_wlan.h | 25 + .../configs/sta_softap/defconfig | 82 + .../esp32c3-devkit/configs/wapi/defconfig | 1 + .../esp32c3-devkit/src/esp32c3_bringup.c | 69 +- 11 files changed, 4546 insertions(+), 536 deletions(-) create mode 100644 arch/risc-v/src/esp32c3/esp32c3_wifi_utils.c create mode 100644 arch/risc-v/src/esp32c3/esp32c3_wifi_utils.h create mode 100644 boards/risc-v/esp32c3/esp32c3-devkit/configs/sta_softap/defconfig diff --git a/arch/risc-v/src/esp32c3/Kconfig b/arch/risc-v/src/esp32c3/Kconfig index 50f052cfdd8..4650c2d82af 100644 --- a/arch/risc-v/src/esp32c3/Kconfig +++ b/arch/risc-v/src/esp32c3/Kconfig @@ -337,6 +337,21 @@ endmenu # Real-Time Timer menu "Wi-Fi configuration" depends on ESP32C3_WIRELESS +choice + prompt "ESP32-C3 Wi-Fi mode" + default ESP32C3_WIFI_STATION + +config ESP32C3_WIFI_STATION + bool "Station mode" + +config ESP32C3_WIFI_SOFTAP + bool "SoftAP mode" + +config ESP32C3_WIFI_STATION_SOFTAP_COEXISTENCE + bool "Station + SoftAP coexistence" + +endchoice # ESP32-C3 Wi-Fi mode + config ESP32C3_WIFI_STATIC_RXBUF_NUM int "Wi-Fi static RX buffer number" default 10 @@ -361,8 +376,8 @@ config ESP32C3_WIFI_RXBA_AMPDU_WZ int "Wi-Fi RX BA AMPDU windown size" default 6 -config ESP32C3_WLAN_RXBUF_NUM - int "WLAN netcard RX buffer number" +config ESP32C3_WLAN_PKTBUF_NUM + int "WLAN netcard packet buffer number per netcard" default 16 config ESP32C3_WIFI_CONNECT_TIMEOUT @@ -371,6 +386,12 @@ config ESP32C3_WIFI_CONNECT_TIMEOUT help Max waiting time of connecting to AP. +config ESP32C3_WIFI_SCAN_RESULT_SIZE + int "Scan result buffer" + default 4096 + help + Maximum scan result buffer size. + config ESP32C3_WIFI_SAVE_PARAM bool "Save Wi-Fi Parameters" default n diff --git a/arch/risc-v/src/esp32c3/Make.defs b/arch/risc-v/src/esp32c3/Make.defs index 757ee2713de..831dce6915f 100644 --- a/arch/risc-v/src/esp32c3/Make.defs +++ b/arch/risc-v/src/esp32c3/Make.defs @@ -117,7 +117,7 @@ clean_context:: INCLUDES += $(shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)esp-wireless-drivers-3rdparty$(DELIM)include) INCLUDES += $(shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)esp-wireless-drivers-3rdparty$(DELIM)include$(DELIM)esp32c3) -CHIP_CSRCS += esp32c3_wlan.c esp32c3_wifi_adapter.c +CHIP_CSRCS += esp32c3_wlan.c esp32c3_wifi_utils.c esp32c3_wifi_adapter.c EXTRA_LIBPATHS += -L $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)esp-wireless-drivers-3rdparty$(DELIM)libs$(DELIM)esp32c3 EXTRA_LIBS += -lcore -lnet80211 -lpp -lsmartconfig -lcoexist -lespnow -lphy -lwpa_supplicant -lwapi diff --git a/arch/risc-v/src/esp32c3/esp32c3_wifi_adapter.c b/arch/risc-v/src/esp32c3/esp32c3_wifi_adapter.c index 8c5b1bdfe16..bdd666a40f4 100644 --- a/arch/risc-v/src/esp32c3/esp32c3_wifi_adapter.c +++ b/arch/risc-v/src/esp32c3/esp32c3_wifi_adapter.c @@ -31,10 +31,12 @@ #include #include #include +#include #include #include #include #include +#include #include "nuttx/kmalloc.h" #include #include "nuttx/spinlock.h" @@ -46,6 +48,7 @@ #include #include #include +#include #include "hardware/esp32c3_syscon.h" #include "esp32c3.h" @@ -53,6 +56,7 @@ #include "esp32c3_irq.h" #include "esp32c3_wifi_adapter.h" #include "esp32c3_rt_timer.h" +#include "esp32c3_wifi_utils.h" #include "espidf_wifi.h" @@ -79,10 +83,37 @@ #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) +#define ESP_MAX_STA_CONN (4) +#define ESP_WIFI_CHANNEL (6) + /**************************************************************************** * 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 SoftAP state */ + +enum wifi_softap_state +{ + WIFI_SOFTAP_STATE_NULL, + WIFI_SOFTAP_STATE_START, + WIFI_SOFTAP_STATE_STOP +}; + /* Wi-Fi interrupt adapter private data */ struct irq_adpt @@ -342,14 +373,41 @@ static int64_t g_phy_rf_en_ts; 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 sem_t g_evtexcl_sem = SEM_INITIALIZER(1); -static sem_t g_connect_sem = SEM_INITIALIZER(0); -static bool g_connected; +static sem_t g_wifiexcl_sem = SEM_INITIALIZER(1); -static uint8_t g_ssid[32]; -static uint8_t g_password[64]; -static uint8_t g_ssid_len; -static uint8_t g_password_len; +/* Wi-Fi adapter reference */ + +static int g_wifi_ref = 0; + +#ifdef ESP32C3_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; +#endif + +#ifdef ESP32C3_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; +#endif /**************************************************************************** * Public Data @@ -492,10 +550,10 @@ ESP_EVENT_DEFINE_BASE(WIFI_EVENT); ****************************************************************************/ /**************************************************************************** - * Name: esp_errno_trans + * Name: osi_errno_trans * * Description: - * Transform from nuttx error code to Wi-Fi adapter error code + * Transform from nuttx Os error code to Wi-Fi adapter error code * * Input Parameters: * ret - NuttX error code @@ -505,7 +563,7 @@ ESP_EVENT_DEFINE_BASE(WIFI_EVENT); * ****************************************************************************/ -static inline int32_t esp_errno_trans(int ret) +static inline int32_t osi_errno_trans(int ret) { if (!ret) { @@ -517,6 +575,70 @@ static inline int32_t esp_errno_trans(int ret) } } +/**************************************************************************** + * 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 * @@ -591,7 +713,7 @@ static void esp_update_time(struct timespec *timespec, uint32_t ticks) } /**************************************************************************** - * Name: esp_event_lock + * Name: esp_wifi_lock * * Description: * Lock or unlock the event process @@ -604,17 +726,25 @@ static void esp_update_time(struct timespec *timespec, uint32_t ticks) * ****************************************************************************/ -static int esp_event_lock(bool lock) +static int esp_wifi_lock(bool lock) { int ret; if (lock) { - ret = nxsem_wait_uninterruptible(&g_evtexcl_sem); + ret = nxsem_wait_uninterruptible(&g_wifiexcl_sem); + if (ret < 0) + { + wlinfo("INFO: Failed to lock Wi-Fi ret=%d\n", ret); + } } else { - ret = nxsem_post(&g_evtexcl_sem); + ret = nxsem_post(&g_wifiexcl_sem); + if (ret < 0) + { + wlinfo("INFO: Failed to unlock Wi-Fi ret=%d\n", ret); + } } return ret; @@ -943,7 +1073,7 @@ static int32_t esp_semphr_take(void *semphr, uint32_t ticks) } } - return esp_errno_trans(ret); + return osi_errno_trans(ret); } /**************************************************************************** @@ -971,7 +1101,7 @@ static int32_t esp_semphr_give(void *semphr) wlerr("ERROR: Failed to post sem error=%d\n", ret); } - return esp_errno_trans(ret); + return osi_errno_trans(ret); } /**************************************************************************** @@ -1167,7 +1297,7 @@ static int32_t esp_mutex_lock(void *mutex_data) wlerr("ERROR: Failed to lock mutex error=%d\n", ret); } - return esp_errno_trans(ret); + return osi_errno_trans(ret); } /**************************************************************************** @@ -1195,7 +1325,7 @@ static int32_t esp_mutex_unlock(void *mutex_data) wlerr("ERROR: Failed to unlock mutex error=%d\n", ret); } - return esp_errno_trans(ret); + return osi_errno_trans(ret); } /**************************************************************************** @@ -1333,7 +1463,7 @@ static int32_t esp_queue_send_generic(void *queue, void *item, } } - return esp_errno_trans(ret); + return osi_errno_trans(ret); } /**************************************************************************** @@ -1838,21 +1968,50 @@ static int esp_event_id_map(int event_id) switch (event_id) { + case WIFI_EVENT_SCAN_DONE: + id = WIFI_ADPT_EVT_SCAN_DONE; + break; + +#ifdef ESP32C3_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 + +#ifdef ESP32C3_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 + default: return -1; } @@ -1891,42 +2050,70 @@ static void esp_evt_work_cb(FAR void *arg) break; } + esp_wifi_lock(true); + switch (evt_adpt->id) { + case WIFI_ADPT_EVT_SCAN_DONE: + esp_wifi_scan_event_parse(); + break; + +#ifdef ESP32C3_WLAN_HAS_STA case WIFI_ADPT_EVT_STA_START: + wlinfo("INFO: Wi-Fi sta start\n"); + g_sta_connected = false; ret = esp_wifi_set_ps(WIFI_PS_NONE); if (ret) { wlerr("ERROR: Failed to close PS\n"); } - ret = esp_wifi_connect(); - if (ret) - { - wlerr("ERROR: Failed to connect\n"); - } break; + case WIFI_ADPT_EVT_STA_CONNECT: - g_connected = true; - ret = nxsem_post(&g_connect_sem); - if (ret) - { - wlerr("ERROR: Failed to post sem error=%d\n", ret); - } + wlinfo("INFO: Wi-Fi sta connect\n"); + g_sta_connected = true; break; + case WIFI_ADPT_EVT_STA_DISCONNECT: - g_connected = false; - ret = esp_wifi_connect(); - if (ret) + wlinfo("INFO: Wi-Fi sta disconnect\n"); + g_sta_connected = false; + if (g_sta_reconnect) { - wlerr("ERROR: Failed to connect\n"); + ret = esp_wifi_connect(); + if (ret) + { + wlerr("ERROR: Failed to connect AP error=%d\n", ret); + } } break; + + case WIFI_ADPT_EVT_STA_STOP: + wlinfo("INFO: Wi-Fi sta stop\n"); + g_sta_connected = false; + break; +#endif + +#ifdef ESP32C3_WLAN_HAS_STA + case WIFI_ADPT_EVT_AP_START: + wlinfo("INFO: Wi-Fi softap start\n"); + 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 default: break; } - esp_event_lock(true); - notify = &g_wifi_notify[evt_adpt->id]; if (notify->assigned) { @@ -1936,12 +2123,12 @@ static void esp_evt_work_cb(FAR void *arg) SI_QUEUE, ¬ify->work); if (ret < 0) { - wlwarn("ERROR: nxsig_notification event ID=%ld failed: %d\n", - evt_adpt->id, ret); + wlwarn("ERROR: nxsig_notification event ID=%d failed: %d\n", + (int)evt_adpt->id, ret); } } - esp_event_lock(false); + esp_wifi_lock(false); kmm_free(evt_adpt); } @@ -3813,6 +4000,211 @@ static unsigned long esp_random_ulong(void) return random(); } +/**************************************************************************** + * Name: esp_wifi_tx_done_cb + * + * Description: + * Wi-Fi TX done callback function. + * + ****************************************************************************/ + +static IRAM_ATTR void esp_wifi_tx_done_cb(uint8_t ifidx, uint8_t *data, + uint16_t *len, bool txstatus) +{ +#if 0 + wlinfo("INFO: ifidx=%d data=%p *len=%p txstatus=%d\n", + ifidx, data, len, txstatus); +#endif + +#ifdef ESP32C3_WLAN_HAS_STA + if (ifidx == ESP_IF_WIFI_STA) + { + if (g_sta_txdone_cb) + { + g_sta_txdone_cb(data, len, txstatus); + } + } + else +#endif +#ifdef ESP32C3_WLAN_HAS_SOFTAP + if (ifidx == ESP_IF_WIFI_AP) + { + if (g_softap_txdone_cb) + { + g_softap_txdone_cb(data, len, txstatus); + } + } + else +#endif + { + wlerr("ERROR: ifidx=%d is error\n", ifidx); + } +} + +/**************************************************************************** + * Name: esp_wifi_set_auth_param + * + * Description: + * Converts a ESP32-C3 authenticate mode values to WEXT authenticate mode. + * + * Input Parameters: + * wifi_auth - ESP32-C3 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; + + default: + wlerr("ERROR: Failed to transfer wireless authmode: %d", + (int)wifi_auth); + break; + } + + return auth_mode; +} + +/**************************************************************************** + * Name: esp_wifi_set_auth_param + * + * Description: + * Converts a ESP32-C3 cipher type values to WEXT cipher type values. + * + * Input Parameters: + * wifi_cipher - ESP32-C3 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("ERROR: Failed to transfer wireless authmode: %d", + (int)wifi_cipher); + break; + } + + return cipher_mode; +} + +/**************************************************************************** + * 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(int freq) +{ + int channel = freq; + + if (channel <= 14) + { + return channel; + } + + 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 libphy.a ****************************************************************************/ @@ -4055,8 +4447,6 @@ esp_err_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; - DEBUGASSERT(timeout_us <= UINT32_MAX); - rt_timer_start(rt_timer, timeout_us, false); return 0; @@ -4081,8 +4471,6 @@ esp_err_t esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t period) { struct rt_timer_s *rt_timer = (struct rt_timer_s *)timer; - DEBUGASSERT(period <= UINT32_MAX); - rt_timer_start(rt_timer, period, true); return 0; @@ -4217,7 +4605,7 @@ esp_err_t esp_wifi_init(const wifi_init_config_t *config) if (ret) { wlerr("ERROR: Failed to initialize Wi-Fi error=%d\n", ret); - return -1; + return ret; } ret = esp_supplicant_init(); @@ -4225,7 +4613,7 @@ esp_err_t esp_wifi_init(const wifi_init_config_t *config) { wlerr("ERROR: Failed to initialize WPA supplicant error=%d\n", ret); esp_wifi_deinit_internal(); - return -1; + return ret; } return 0; @@ -4266,74 +4654,6 @@ esp_err_t esp_wifi_deinit(void) 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: - * 0 if success or others if fail - * - ****************************************************************************/ - -int esp_wifi_sta_send_data(void *pbuf, uint32_t len) -{ - int ret; - - ret = esp_wifi_internal_tx(WIFI_IF_STA, pbuf, len); - - return ret; -} - -/**************************************************************************** - * Name: esp_wifi_sta_register_recv_cb - * - * Description: - * Register Wi-Fi receive packet callback function - * - * Input Parameters: - * input_cb - Receive callback function - * - * Returned Value: - * 0 if success or others if fail - * - ****************************************************************************/ - -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 ret; -} - -/**************************************************************************** - * 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_free_eb * @@ -4376,7 +4696,7 @@ int esp_wifi_notify_subscribe(pid_t pid, FAR struct sigevent *event) wlinfo("PID=%d event=%p\n", pid, event); - esp_event_lock(true); + esp_wifi_lock(true); if (event->sigev_notify == SIGEV_SIGNAL) { @@ -4439,7 +4759,7 @@ int esp_wifi_notify_subscribe(pid_t pid, FAR struct sigevent *event) wlerr("ERROR: sigev_notify %d is invalid\n", event->sigev_signo); } - esp_event_lock(false); + esp_wifi_lock(false); return ret; } @@ -4448,7 +4768,7 @@ int esp_wifi_notify_subscribe(pid_t pid, FAR struct sigevent *event) * Name: esp_wifi_adapter_init * * Description: - * Initialize ESP32C3 Wi-Fi adapter + * Initialize Wi-Fi adapter * * Input Parameters: * None @@ -4463,13 +4783,25 @@ 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("INFO: Wi-Fi adapter is already initialized\n"); + g_wifi_ref++; + esp_wifi_lock(false); + return OK; + } + ret = esp32c3_rt_timer_init(); if (ret < 0) { wlerr("ERROR: Failed to initialize RT timer error=%d\n", ret); - return -1; + goto errout_init_timer; } + sq_init(&g_wifi_evt_queue); + #ifdef CONFIG_ESP32C3_WIFI_SAVE_PARAM wifi_cfg.nvs_enable = 1; #else @@ -4499,148 +4831,1867 @@ int esp_wifi_adapter_init(void) if (ret) { wlerr("ERROR: Failed to initialize Wi-Fi error=%d\n", ret); - esp32c3_rt_timer_deinit(); - return -1; + ret = wifi_errno_trans(ret); + goto errout_init_wifi; } - sq_init(&g_wifi_evt_queue); + ret = esp_wifi_set_tx_done_cb(esp_wifi_tx_done_cb); + if (ret) + { + wlerr("ERROR: Failed to register TX done callback ret=%d\n", ret); + ret = wifi_errno_trans(ret); + goto errout_init_txdone; + } - return 0; + ret = esp_wifi_scan_init(); + if (ret < 0) + { + nerr("ERROR: Initialize Wi-Fi scan parameter error: %d\n", ret); + return ret; + } + + g_wifi_ref++; + + wlinfo("INFO: OK to initialize Wi-Fi adapter\n"); + + esp_wifi_lock(false); + + return OK; + +errout_init_txdone: + esp_wifi_deinit(); +errout_init_wifi: + esp32c3_rt_timer_deinit(); +errout_init_timer: + esp_wifi_lock(false); + return ret; } /**************************************************************************** - * Name: esp_wifi_set_password - * - * Description: - * Set Wi-Fi password - * - * Input Parameters: - * pdata - Password buffer pointer - * len - Password length - * - * Returned Value: - * 0 if success or -1 if fail - * + * Station functions ****************************************************************************/ -int esp_wifi_set_password(const uint8_t *pdata, uint8_t len) -{ - memcpy(g_password, pdata, len); - g_password_len = len; - - return 0; -} +#ifdef ESP32C3_WLAN_HAS_STA /**************************************************************************** - * Name: esp_wifi_set_ssid + * Name: esp_wifi_sta_start * * Description: - * Set Wi-Fi SSID - * - * Input Parameters: - * pdata - SSID buffer pointer - * len - SSID length - * - * Returned Value: - * 0 if success or -1 if fail - * - ****************************************************************************/ - -int esp_wifi_set_ssid(const uint8_t *pdata, uint8_t len) -{ - memcpy(g_ssid, pdata, len); - g_ssid_len = len; - - return 0; -} - -/**************************************************************************** - * Name: esp_wifi_connect_internal - * - * Description: - * Trigger Wi-Fi connection action + * Start Wi-Fi station. * * Input Parameters: * None * * Returned Value: - * 0 if success or -1 if fail + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. * ****************************************************************************/ -int esp_wifi_connect_internal(void) +int esp_wifi_sta_start(void) { int ret; - wifi_config_t wifi_cfg; - struct timespec timeout; + wifi_mode_t mode; - if (g_connected) - { - wlinfo("INFO: Wi-Fi has connected AP\n"); - return 0; - } + esp_wifi_lock(true); - ret = esp_wifi_set_mode(WIFI_MODE_STA); + ret = esp_wifi_stop(); if (ret) { - wlerr("ERROR: Failed to set station mode error=%d\n", ret); - esp_wifi_deinit(); - return -1; + wlinfo("INFO: Failed to stop Wi-Fi ret=%d\n", ret); } - memset(&wifi_cfg, 0, sizeof(wifi_config_t)); - memcpy((char *)wifi_cfg.sta.ssid, g_ssid, g_ssid_len); - memcpy((char *)wifi_cfg.sta.password, g_password, g_password_len); +#ifdef ESP32C3_WLAN_HAS_SOFTAP + if (g_softap_started) + { + mode = WIFI_MODE_APSTA; + } +#else + mode = WIFI_MODE_STA; +#endif - ret = esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_cfg); + ret = esp_wifi_set_mode(mode); if (ret) { - wlerr("ERROR: Failed to set Wi-Fi config error=%d\n", ret); - return -1; + wlerr("ERROR: Failed to set Wi-Fi mode=%d ret=%d\n", mode, ret); + ret = wifi_errno_trans(ret); + goto errout_set_mode; } ret = esp_wifi_start(); if (ret) { - wlerr("ERROR: Failed to set start config error=%d\n", ret); - return -1; + wlerr("ERROR: Failed to start Wi-Fi with mode=%d ret=%d\n", mode, ret); + ret = wifi_errno_trans(ret); + goto errout_set_mode; } - clock_gettime(CLOCK_REALTIME, &timeout); - timeout.tv_sec += WIFI_CONNECT_TIMEOUT; - ret = nxsem_timedwait(&g_connect_sem, &timeout); + g_sta_started = true; + + wlinfo("INFO: OK to start Wi-Fi station\n"); + + esp_wifi_lock(false); + return OK; + +errout_set_mode: + 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) { - wlerr("ERROR: Failed to wait sem error=%d\n", ret); - esp_wifi_stop(); - return -1; + wlinfo("INFO: Failed to stop Wi-Fi ret=%d\n", ret); } - if (!g_connected) + g_sta_started = false; + +#ifdef ESP32C3_WLAN_HAS_SOFTAP + if (g_softap_started) { - wlerr("ERROR: Process connection error\n"); - esp_wifi_stop(); - return -1; - } + ret = esp_wifi_set_mode(WIFI_MODE_AP); + if (ret) + { + wlerr("ERROR: Failed to set Wi-Fi AP mode ret=%d\n", ret); + ret = wifi_errno_trans(ret); + goto errout_set_mode; + } - return 0; + ret = esp_wifi_start(); + if (ret) + { + wlerr("ERROR: Failed to start Wi-Fi AP ret=%d\n", ret); + ret = wifi_errno_trans(ret); + goto errout_set_mode; + } + } +#endif + + wlinfo("INFO: OK to stop Wi-Fi station\n"); + + esp_wifi_lock(false); + return OK; + +#ifdef ESP32C3_WLAN_HAS_SOFTAP +errout_set_mode: + esp_wifi_lock(true); + return ret; +#endif +} + +/**************************************************************************** + * 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(FAR void *pbuf, size_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 txDone callback function of type wifi_tx_done_cb_t + * Register the station TX done callback function. * * Input Parameters: - * callback - The callback function + * 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_register_txdone_cb(void *callback) +int esp_wifi_sta_read_mac(uint8_t *mac) { - return esp_wifi_set_tx_done_cb((wifi_tx_done_cb_t)callback); + 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; + len = ext->key_len; + + if (set && len > PWD_MAX_LEN) + { + return -EINVAL; + } + + memset(&wifi_cfg, 0x0, sizeof(wifi_config_t)); + ret = esp_wifi_get_config(WIFI_IF_STA, &wifi_cfg); + if (ret) + { + wlerr("ERROR: Failed to get Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + if (set) + { + memcpy(wifi_cfg.sta.password, pdata, len); + + wifi_cfg.sta.pmf_cfg.capable = true; + + ret = esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg); + if (ret) + { + wlerr("ERROR: Failed to set Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + } + else + { + size = strnlen((char *)wifi_cfg.sta.password, PWD_MAX_LEN); + if (len < size) + { + return -EINVAL; + } + else + { + len = size; + memcpy(pdata, wifi_cfg.sta.password, len); + } + + if (g_sta_connected) + { + wifi_ap_record_t ap_info; + + ret = esp_wifi_sta_get_ap_info(&ap_info); + if (ret) + { + wlerr("ERROR: 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("ERROR: 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("INFO: 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; + } + + memset(&wifi_cfg, 0x0, sizeof(wifi_config_t)); + ret = esp_wifi_get_config(WIFI_IF_STA, &wifi_cfg); + if (ret) + { + wlerr("ERROR: Failed to get Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + if (set) + { + memcpy(wifi_cfg.sta.ssid, pdata, len); + + ret = esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg); + if (ret) + { + wlerr("ERROR: Failed to set Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + } + 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("\nINFO: 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; + + memset(&wifi_cfg, 0x0, sizeof(wifi_config_t)); + ret = esp_wifi_get_config(WIFI_IF_STA, &wifi_cfg); + if (ret) + { + wlerr("ERROR: Failed to get Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + sockaddr = &iwr->u.ap_addr; + pdata = sockaddr->sa_data; + + if (set) + { + wifi_cfg.sta.bssid_set = true; + memcpy(wifi_cfg.sta.bssid, pdata, 6); + + ret = esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg); + if (ret) + { + wlerr("ERROR: Failed to set Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + } + else + { + memcpy(pdata, wifi_cfg.sta.bssid, 6); + } + + 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("INFO: Wi-Fi has connected AP\n"); + esp_wifi_lock(false); + return OK; + } + + g_sta_reconnect = true; + + ret = esp_wifi_connect(); + if (ret) + { + wlerr("ERROR: Failed to connect ret=%d\n", ret); + ret = wifi_errno_trans(ret); + goto errout_wifi_connect; + } + + 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("INFO: Failed to connect to AP\n"); + return -1; + } + + wlinfo("INFO: Wi-Fi connect complete, success\n"); + return OK; + +errout_wifi_connect: + 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("ERROR: Failed to disconnect ret=%d\n", ret); + ret = wifi_errno_trans(ret); + } + else + { + wlinfo("INFO: Wi-Fi disconnect complete, success\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_ap_record_t ap_info; + + if (set) + { + return OK; + } + else + { + if (g_sta_connected == false) + { + return -ENOTCONN; + } + + ret = esp_wifi_sta_get_ap_info(&ap_info); + if (ret) + { + wlerr("ERROR: 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("ERROR: 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; + wifi_config_t wifi_cfg; + + memset(&wifi_cfg, 0x0, sizeof(wifi_config_t)); + if (set && (iwr->u.freq.flags == IW_FREQ_FIXED)) + { + ret = esp_wifi_get_config(WIFI_IF_STA, &wifi_cfg); + if (ret) + { + wlerr("ERROR: Failed to get Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + wifi_cfg.sta.channel = esp_freq_to_channel(iwr->u.freq.m); + + ret = esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg); + if (ret) + { + wlerr("ERROR: Failed to set Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + +#ifdef CONFIG_DEBUG_WIRELESS_INFO + wlinfo("\nINFO: Wi-Fi station channel=%d\n", wifi_cfg.sta.channel); +#endif + } + else + { + if (g_sta_connected) + { + wifi_ap_record_t ap_info; + + ret = esp_wifi_sta_get_ap_info(&ap_info); + if (ret) + { + wlerr("ERROR: 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("ERROR: 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; +} + +/**************************************************************************** + * 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("ERROR: 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("ERROR: 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_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) +{ + 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("ERROR: 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("ERROR: Invalid input arguments\r\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("ERROR: Failed to Configure country ret=%d\n", ret); + return wifi_errno_trans(ret); + } + } + else + { + return -ENOSYS; + } + + return OK; +} + +/**************************************************************************** + * 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("ERROR: Failed to get AP record ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + iwr->u.sens.value = -(ap_info.rssi); + } + + return OK; +} +#endif + +/**************************************************************************** + * SoftAP functions + ****************************************************************************/ + +#ifdef ESP32C3_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("INFO: Failed to stop Wi-Fi ret=%d\n", ret); + } + +#ifdef ESP32C3_WLAN_HAS_STA + if (g_sta_started) + { + mode = WIFI_MODE_APSTA; + } +#else + mode = WIFI_MODE_AP; +#endif + + ret = esp_wifi_set_mode(mode); + if (ret) + { + wlerr("ERROR: Failed to set Wi-Fi mode=%d ret=%d\n", mode, ret); + ret = wifi_errno_trans(ret); + goto errout_set_mode; + } + + ret = esp_wifi_start(); + if (ret) + { + wlerr("ERROR: Failed to start Wi-Fi with mode=%d ret=%d\n", mode, ret); + ret = wifi_errno_trans(ret); + goto errout_set_mode; + } + + g_softap_started = true; + + wlinfo("INFO: OK to start Wi-Fi SoftAP\n"); + + esp_wifi_lock(false); + return OK; + +errout_set_mode: + 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("INFO: Failed to stop Wi-Fi ret=%d\n", ret); + } + + g_softap_started = false; + +#ifdef ESP32C3_WLAN_HAS_STA + if (g_sta_started) + { + ret = esp_wifi_set_mode(WIFI_MODE_STA); + if (ret) + { + wlerr("ERROR: Failed to set Wi-Fi AP mode ret=%d\n", ret); + ret = wifi_errno_trans(ret); + goto errout_set_mode; + } + + ret = esp_wifi_start(); + if (ret) + { + wlerr("ERROR: Failed to start Wi-Fi AP ret=%d\n", ret); + ret = wifi_errno_trans(ret); + goto errout_set_mode; + } + } +#endif + + wlinfo("INFO: OK to stop Wi-Fi SoftAP\n"); + + esp_wifi_lock(false); + return OK; + +#ifdef ESP32C3_WLAN_HAS_STA +errout_set_mode: + esp_wifi_lock(true); + return ret; +#endif +} + +/**************************************************************************** + * 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(FAR 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); + + len = ext->key_len; + + if (set && len > PWD_MAX_LEN) + { + return -EINVAL; + } + + memset(&wifi_cfg, 0x0, sizeof(wifi_config_t)); + ret = esp_wifi_get_config(WIFI_IF_AP, &wifi_cfg); + if (ret) + { + wlerr("ERROR: Failed to get Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + ext = (struct iw_encode_ext *)(iwr->u.encoding.pointer); + pdata = (uint8_t *)(ext + 1); + len = ext->key_len; + + if (set) + { + wifi_cfg.ap.max_connection = ESP_MAX_STA_CONN; + memcpy(wifi_cfg.ap.password, pdata, len); + wifi_cfg.ap.password[len] = '\0'; + if (len) + { + wifi_cfg.ap.authmode = WIFI_AUTH_WPA_WPA2_PSK; + } + + ret = esp_wifi_set_config(WIFI_IF_AP, &wifi_cfg); + if (ret) + { + wlerr("ERROR: Failed to set Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + } + 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("INFO: 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; + } + + memset(&wifi_cfg, 0x0, sizeof(wifi_config_t)); + ret = esp_wifi_get_config(WIFI_IF_AP, &wifi_cfg); + if (ret) + { + wlerr("ERROR: Failed to get Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + if (set) + { + memcpy(wifi_cfg.ap.ssid, pdata, len); + + ret = esp_wifi_set_config(WIFI_IF_AP, &wifi_cfg); + if (ret) + { + wlerr("ERROR: Failed to set Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + } + 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("INFO: 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) +{ + 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; + + if (set) + { + memset(&wifi_cfg, 0x0, sizeof(wifi_config_t)); + ret = esp_wifi_get_config(WIFI_IF_AP, &wifi_cfg); + if (ret) + { + wlerr("ERROR: Failed to get Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + 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; + + default: + wlerr("ERROR: 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: + wifi_cfg.ap.authmode = WIFI_AUTH_WPA_PSK; + break; + + case IW_AUTH_CIPHER_CCMP: + case IW_AUTH_CIPHER_AES_CMAC: + wifi_cfg.ap.authmode = WIFI_AUTH_WPA2_PSK; + break; + + default: + wlerr("ERROR: 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("ERROR: Unknown cmd %d\n", cmd); + return -EINVAL; + } + + ret = esp_wifi_set_config(WIFI_IF_AP, &wifi_cfg); + if (ret) + { + wlerr("ERROR: Failed to set Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + } + 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; + + memset(&wifi_cfg, 0x0, sizeof(wifi_config_t)); + ret = esp_wifi_get_config(WIFI_IF_AP, &wifi_cfg); + if (ret) + { + wlerr("ERROR: Failed to get Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + if (set) + { + int channel = esp_freq_to_channel(iwr->u.freq.m); + + wifi_cfg.ap.channel = channel; + + ret = esp_wifi_set_config(WIFI_IF_AP, &wifi_cfg); + if (ret) + { + wlerr("ERROR: Failed to set Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + } + 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 diff --git a/arch/risc-v/src/esp32c3/esp32c3_wifi_adapter.h b/arch/risc-v/src/esp32c3/esp32c3_wifi_adapter.h index a1bd411b7bf..237c249229d 100644 --- a/arch/risc-v/src/esp32c3/esp32c3_wifi_adapter.h +++ b/arch/risc-v/src/esp32c3/esp32c3_wifi_adapter.h @@ -44,15 +44,39 @@ extern "C" * Pre-processor Definitions ****************************************************************************/ +#if defined(CONFIG_ESP32C3_WIFI_STATION) +# define ESP32C3_WLAN_HAS_STA +# define ESP32C3_WLAN_STA_DEVNO 0 +# define ESP32C3_WLAN_DEVS 1 +#elif defined(CONFIG_ESP32C3_WIFI_SOFTAP) +# define ESP32C3_WLAN_HAS_SOFTAP +# define ESP32C3_WLAN_SOFTAP_DEVNO 0 +# define ESP32C3_WLAN_DEVS 1 +#elif defined(CONFIG_ESP32C3_WIFI_STATION_SOFTAP_COEXISTENCE) +# define ESP32C3_WLAN_HAS_STA +# define ESP32C3_WLAN_HAS_SOFTAP +# define ESP32C3_WLAN_STA_DEVNO 0 +# define ESP32C3_WLAN_SOFTAP_DEVNO 1 +# define ESP32C3_WLAN_DEVS 2 +#endif + +#define SSID_MAX_LEN (32) +#define PWD_MAX_LEN (64) + /* Wi-Fi event ID */ enum wifi_adpt_evt_e { - WIFI_ADPT_EVT_STA_START = 0, + 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, }; @@ -60,8 +84,9 @@ enum wifi_adpt_evt_e typedef void (*wifi_evt_cb_t)(void *p); -typedef void (* wifi_tx_done_cb_t)(uint8_t ifidx, uint8_t *data, - uint16_t *len, bool txstatus); +/* Wi-Fi TX done callback function */ + +typedef void (*wifi_txdone_cb_t)(uint8_t *data, uint16_t *len, bool status); /**************************************************************************** * Public Function Prototypes @@ -71,7 +96,7 @@ typedef void (* wifi_tx_done_cb_t)(uint8_t ifidx, uint8_t *data, * Name: esp_wifi_adapter_init * * Description: - * Initialize ESP32 Wi-Fi adapter + * Initialize Wi-Fi adapter * * Input Parameters: * None @@ -83,74 +108,6 @@ typedef void (* wifi_tx_done_cb_t)(uint8_t ifidx, uint8_t *data, int esp_wifi_adapter_init(void); -/**************************************************************************** - * 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, FAR struct sigevent *event); - -/**************************************************************************** - * 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: - * 0 if success or others if fail - * - ****************************************************************************/ - -int esp_wifi_sta_send_data(void *pbuf, uint32_t len); - -/**************************************************************************** - * Name: esp_wifi_sta_register_recv_cb - * - * Description: - * Register Wi-Fi receive packet callback function - * - * Input Parameters: - * input_cb - Receive callback function - * - * Returned Value: - * 0 if success or others if fail - * - ****************************************************************************/ - -int esp_wifi_sta_register_recv_cb(int (*recv_cb)(void *buffer, - uint16_t len, - void *eb)); - -/**************************************************************************** - * 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_free_eb * @@ -168,70 +125,696 @@ int esp_wifi_sta_read_mac(uint8_t *mac); void esp_wifi_free_eb(void *eb); /**************************************************************************** - * Name: esp_wifi_set_password + * Name: esp_wifi_notify_subscribe * * Description: - * Set Wi-Fi password + * Enable event notification * * Input Parameters: - * pdata - Password buffer pointer - * len - Password length + * pid - Task PID + * event - Signal event data pointer * * Returned Value: * 0 if success or -1 if fail * ****************************************************************************/ -int esp_wifi_set_password(const uint8_t *pdata, uint8_t len); +int esp_wifi_notify_subscribe(pid_t pid, FAR struct sigevent *event); + +#ifdef ESP32C3_WLAN_HAS_STA /**************************************************************************** - * Name: esp_wifi_set_ssid + * Name: esp_wifi_sta_start * * Description: - * Set Wi-Fi SSID - * - * Input Parameters: - * pdata - SSID buffer pointer - * len - SSID length - * - * Returned Value: - * 0 if success or -1 if fail - * - ****************************************************************************/ - -int esp_wifi_set_ssid(const uint8_t *pdata, uint8_t len); - -/**************************************************************************** - * Name: esp_wifi_connect_internal - * - * Description: - * Trigger Wi-Fi connection action + * Start Wi-Fi station. * * Input Parameters: * None * * Returned Value: - * 0 if success or -1 if fail + * OK on success (positive non-zero values are cmd-specific) + * Negated errno returned on failure. * ****************************************************************************/ -int esp_wifi_connect_internal(void); +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(FAR void *pbuf, size_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 txDone callback function of type wifi_tx_done_cb_t + * Register the station TX done callback function. * * Input Parameters: - * callback - The callback function + * 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_register_txdone_cb(void *callback); +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 + +#ifdef ESP32C3_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 + * + * 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 #ifdef __cplusplus } diff --git a/arch/risc-v/src/esp32c3/esp32c3_wifi_utils.c b/arch/risc-v/src/esp32c3/esp32c3_wifi_utils.c new file mode 100644 index 00000000000..5fd5c31acb1 --- /dev/null +++ b/arch/risc-v/src/esp32c3/esp32c3_wifi_utils.c @@ -0,0 +1,523 @@ +/**************************************************************************** + * arch/risc-v/src/esp32c3/esp32c3_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 "esp32c3_wifi_adapter.h" +#include "esp32c3_wifi_utils.h" +#include "espidf_wifi.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_ESP32C3_WIFI_SCAN_RESULT_SIZE +# define WIFI_SCAN_RESULT_SIZE CONFIG_ESP32C3_WIFI_SCAN_RESULT_SIZE +#else +# define WIFI_SCAN_RESULT_SIZE (4096) +#endif + +#define SCAN_TIME_SEC (5) + +#ifndef MIN +# define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +/**************************************************************************** + * 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_s +{ + 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_s g_scan_priv; + +/**************************************************************************** + * 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_s *priv = &g_scan_priv; + wifi_scan_config_t *config = NULL; + struct iw_scan_req *req; + int ret = 0; + uint8_t target_ssid[SSID_MAX_LEN + 1] = + { + 0 + }; + + 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; + } + + 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 */ + + memcpy(&target_ssid[0], req->essid, req->essid_len); + config->ssid = &target_ssid[0]; + config->ssid[req->essid_len] = '\0'; + } + } + else + { + /* Default scan parameters */ + + wlinfo("INFO: Use default scan parameters\n"); + config->scan_type = WIFI_SCAN_TYPE_ACTIVE; /* Active scan */ + } + + esp_wifi_start(); + + esp_wifi_scan_stop(); + + ret = esp_wifi_scan_start(config, false); + if (ret != OK) + { + wlerr("ERROR: Scan error, ret: %d\n", ret); + } + 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 != NULL) + { + kmm_free(config); + config = NULL; + 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; + struct timespec abstime; + static bool scan_block = false; + struct wifi_scan_result_s *priv = &g_scan_priv; + + if (g_scan_priv.scan_status == ESP_SCAN_RUN) + { + irqstate_t irqstate = enter_critical_section(); + if (scan_block == false) + { + scan_block = true; + leave_critical_section(irqstate); + clock_gettime(CLOCK_REALTIME, &abstime); + abstime.tv_sec += SCAN_TIME_SEC; + nxsem_timedwait(&priv->scan_signal, &abstime); + scan_block = false; + } + else + { + leave_critical_section(irqstate); + 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 (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; + goto exit_failed; + } + + if (priv->scan_result_size <= 0) + { + ret = OK; + iwr->u.data.length = 0; + goto exit_free_buffer; + } + + /* 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_s *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; + + esp_wifi_scan_get_ap_num(&bss_total); + if (bss_total == 0) + { + wlinfo("INFO: None AP is scanned\n"); + return; + } + + ap_list_buffer = kmm_calloc(bss_total, sizeof(wifi_ap_record_t)); + if (ap_list_buffer == NULL) + { + wlerr("ERROR: Failed to calloc buffer to print scan results"); + 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; + for (bss_count = 0; bss_count < bss_total; bss_count++) + { + 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 = (FAR 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 == false) + { + wlerr("ERROR: No more space in scan_result buffer\n"); + } + + if (ap_list_buffer != NULL) + { + kmm_free(ap_list_buffer); + ap_list_buffer = NULL; + } + + g_scan_priv.scan_status = ESP_SCAN_DONE; + nxsem_post(&priv->scan_signal); +} + +/**************************************************************************** + * Name: esp_wifi_scan_init + * + * Description: + * Initialize Wi-Fi scan parameter. + * + * Input Parameters: + * None + * + * Returned Value: + * OK is returned on success. Otherwise, a negated errno value is returned. + * + ****************************************************************************/ + +int esp_wifi_scan_init(void) +{ + int ret; + struct wifi_scan_result_s *scan_priv = &g_scan_priv; + + /* Initialize the scan structure */ + + memset(scan_priv, 0, sizeof(struct wifi_scan_result_s)); + + /* Init scan signal */ + + if ((ret = nxsem_init(&scan_priv->scan_signal, 0, 0)) != OK) + { + wlerr("ERROR: Initialization scan signal failed: %d\n", ret); + return ret; + } + + if ((ret = nxsem_set_protocol(&scan_priv->scan_signal, + SEM_PRIO_NONE)) != OK) + { + wlerr("ERROR: Set semaphore protocol attribute failed: %d\n", ret); + } + + return ret; +} diff --git a/arch/risc-v/src/esp32c3/esp32c3_wifi_utils.h b/arch/risc-v/src/esp32c3/esp32c3_wifi_utils.h new file mode 100644 index 00000000000..bfce2ac63e7 --- /dev/null +++ b/arch/risc-v/src/esp32c3/esp32c3_wifi_utils.h @@ -0,0 +1,120 @@ +/**************************************************************************** + * arch/risc-v/src/esp32c3/esp32c3_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_RISCV_SRC_ESP32C3_ESP32C3_UTILS_H +#define __ARCH_RISCV_SRC_ESP32C3_ESP32C3_UTILS_H + +#include +#include + +#include + +#ifndef __ASSEMBLY__ + +#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); + +/**************************************************************************** + * Name: esp_wifi_scan_init + * + * Description: + * Initialize Wi-Fi scan parameter. + * + * Input Parameters: + * None + * + * Returned Value: + * OK is returned on success. Otherwise, a negated errno value is returned. + * + ****************************************************************************/ + +int esp_wifi_scan_init(void); + +#ifdef __cplusplus +} +#endif +#undef EXTERN + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_XTENSA_SRC_ESP32_ESP32_UTILS_H */ diff --git a/arch/risc-v/src/esp32c3/esp32c3_wlan.c b/arch/risc-v/src/esp32c3/esp32c3_wlan.c index 312b828aaf0..ba549d6e52e 100644 --- a/arch/risc-v/src/esp32c3/esp32c3_wlan.c +++ b/arch/risc-v/src/esp32c3/esp32c3_wlan.c @@ -24,6 +24,8 @@ #include +#ifdef CONFIG_ESP32C3_WIRELESS + #include #include #include @@ -41,16 +43,14 @@ # include #endif +#include "esp32c3_wlan.h" +#include "esp32c3_wifi_utils.h" #include "esp32c3_wifi_adapter.h" /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ -/* WLAN station device ID */ - -#define WLAN_STA_DEVNO (0) - /* TX poll delay = 1 seconds. * CLK_TCK is the number of clock ticks per second */ @@ -77,9 +77,9 @@ #define WLAN_BUF_SIZE (CONFIG_NET_ETH_PKTSIZE) -/* Wi-Fi receive buffer number */ +/* WLAN packet buffer number */ -#define WLAN_RXBUF_NUM (CONFIG_ESP32C3_WLAN_RXBUF_NUM) +#define WLAN_PKTBUF_NUM (CONFIG_ESP32C3_WLAN_PKTBUF_NUM) /* Receive threshold which allows the receive function to trigger a scheduler * to activate the application if possible. @@ -92,13 +92,15 @@ # endif #endif +#define MAC_LEN (6) + /**************************************************************************** * Private Types ****************************************************************************/ -/* Receive buffer */ +/* WLAN packet buffer */ -struct wlan_rxbuf +struct wlan_pktbuf_s { sq_entry_t entry; /* Queue entry */ @@ -108,12 +110,37 @@ struct wlan_rxbuf uint16_t len; /* Packet data length */ }; +/* WLAN operations */ + +struct wlan_ops_s +{ + int (*start)(void); + int (*send)(FAR 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, FAR struct sigevent *event); + int (*stop)(void); +}; + /* The wlan_priv_s encapsulates all state information for a single * hardware interface */ struct wlan_priv_s { + bool ref; /* Reference count */ + bool ifup; /* true:ifup false:ifdown */ struct wdog_s txpoll; /* TX poll timer */ @@ -124,27 +151,25 @@ struct wlan_priv_s struct work_s pollwork; /* Poll work */ struct work_s toutwork; /* Send packet timeout work */ + const struct wlan_ops_s *ops; /* WLAN operations */ + /* This holds the information visible to the NuttX network */ struct net_driver_s dev; - /* TX buffer */ + /* Packet buffer cache */ - uint8_t txbuf[WLAN_BUF_SIZE]; + struct wlan_pktbuf_s pktbuf[WLAN_PKTBUF_NUM]; - /* Rest of the data in the TX buffer that need to be sent */ - - uint8_t txrst; - - /* RX buffer cache */ - - struct wlan_rxbuf rxbuf[WLAN_RXBUF_NUM]; - - /* RX buffer queue */ + /* RX packet queue */ sq_queue_t rxb; - /* Free buffer queue */ + /* TX ready packet queue */ + + sq_queue_t txb; + + /* Free packet buffer queue */ sq_queue_t freeb; }; @@ -153,7 +178,53 @@ struct wlan_priv_s * Private Data ****************************************************************************/ -static struct wlan_priv_s g_wlan_priv; +static struct wlan_priv_s g_wlan_priv[ESP32C3_WLAN_DEVS]; + +#ifdef ESP32C3_WLAN_HAS_STA +static const struct wlan_ops_s 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 + +#ifdef ESP32C3_WLAN_HAS_SOFTAP +static const struct wlan_ops_s 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 /**************************************************************************** * Private Function Prototypes @@ -161,7 +232,7 @@ static struct wlan_priv_s g_wlan_priv; /* Common TX logic */ -static int wlan_transmit(FAR struct wlan_priv_s *priv); +static void wlan_transmit(FAR struct wlan_priv_s *priv); static void wlan_rxpoll(FAR void *arg); static int wlan_txpoll(FAR struct net_driver_s *dev); static void wlan_dopoll(FAR struct wlan_priv_s *priv); @@ -195,9 +266,10 @@ static int wlan_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg); #endif -static void wlan_tx_done(uint8_t ifidx, uint8_t *data, - uint16_t *len, bool txstatus); -static int wlan_rx_done(void *buffer, uint16_t len, void *eb); +#ifdef ESP32C3_WLAN_HAS_STA +static int wlan_sta_set_linkstatus(FAR struct net_driver_s *dev, + bool linkstatus); +#endif /**************************************************************************** * Private Functions @@ -234,17 +306,16 @@ static inline void wlan_init_buffer(struct wlan_priv_s *priv) flags = enter_critical_section(); - priv->txrst = 0; - 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_RXBUF_NUM; i++) + for (i = 0; i < WLAN_PKTBUF_NUM; i++) { - sq_addlast(&priv->rxbuf[i].entry, &priv->freeb); + sq_addlast(&priv->pktbuf[i].entry, &priv->freeb); } leave_critical_section(flags); @@ -264,23 +335,24 @@ static inline void wlan_init_buffer(struct wlan_priv_s *priv) * ****************************************************************************/ -static inline struct wlan_rxbuf *wlan_alloc_buffer(struct wlan_priv_s *priv) +static struct wlan_pktbuf_s *wlan_alloc_buffer( + struct wlan_priv_s *priv) { sq_entry_t *entry; irqstate_t flags; - struct wlan_rxbuf *rxbuf = NULL; + struct wlan_pktbuf_s *pktbuf = NULL; flags = enter_critical_section(); entry = sq_remfirst(&priv->freeb); - if (entry) + if (entry != NULL) { - rxbuf = container_of(entry, struct wlan_rxbuf, entry); + pktbuf = container_of(entry, struct wlan_pktbuf_s, entry); } leave_critical_section(flags); - return rxbuf; + return pktbuf; } /**************************************************************************** @@ -291,7 +363,7 @@ static inline struct wlan_rxbuf *wlan_alloc_buffer(struct wlan_priv_s *priv) * * Input Parameters: * priv - Reference to the driver state structure - * buffer - A pointer to the buffer to be freed + * buffer - A pointer to the packet buffer to be freed * * Returned Value: * None @@ -301,133 +373,173 @@ static inline struct wlan_rxbuf *wlan_alloc_buffer(struct wlan_priv_s *priv) static inline void wlan_free_buffer(struct wlan_priv_s *priv, uint8_t *buffer) { - struct wlan_rxbuf *rxbuf; + struct wlan_pktbuf_s *pktbuf; irqstate_t flags; flags = enter_critical_section(); - rxbuf = container_of(buffer, struct wlan_rxbuf, buffer); - sq_addlast(&rxbuf->entry, &priv->freeb); + pktbuf = container_of(buffer, struct wlan_pktbuf_s, buffer); + sq_addlast(&pktbuf->entry, &priv->freeb); leave_critical_section(flags); } /**************************************************************************** - * Name: wifi_tx_available + * Function: wlan_cache_txpkt_tail * * Description: - * Check if Wi-Fi can send data. This function will re-send the rest of the - * data that we failed to send. + * Cache packet from dev->d_buf into tail of TX ready queue. * * Input Parameters: * priv - Reference to the driver state structure * * Returned Value: - * true if available or false if unavailable + * None * ****************************************************************************/ -static bool wifi_tx_available(FAR struct wlan_priv_s *priv) +static inline void wlan_cache_txpkt_tail(struct wlan_priv_s *priv) { - int ret; + struct wlan_pktbuf_s *pktbuf; + irqstate_t flags; + struct net_driver_s *dev = &priv->dev; - if (priv->txrst) - { - ret = esp_wifi_sta_send_data(priv->txbuf, priv->txrst); - if (ret) - { - ninfo("ERROR: Failed to transmit the rest of the frame\n"); - return false; - } - else - { - priv->txrst = 0; - } - } + pktbuf = container_of(dev->d_buf, struct wlan_pktbuf_s, buffer); + pktbuf->len = dev->d_len; - return true; + flags = enter_critical_section(); + sq_addlast(&pktbuf->entry, &priv->txb); + leave_critical_section(flags); + + dev->d_buf = NULL; + dev->d_len = 0; } /**************************************************************************** - * Name: wlan_transmit + * Function: wlan_add_txpkt_head * * Description: - * Send the data to Wi-Fi driver. If this sending fails, cache the data - * and re-send it when TX done callback or timer poll function triggers. + * Add packet into head of TX ready queue. * * Input Parameters: * priv - Reference to the driver state structure * * Returned Value: - * OK on success; a negated errno on failure + * None * ****************************************************************************/ -static int wlan_transmit(FAR struct wlan_priv_s *priv) +static inline void wlan_add_txpkt_head(struct wlan_priv_s *priv, + struct wlan_pktbuf_s *pktbuf) { - int ret; - struct net_driver_s *dev = &priv->dev; - void *buffer = dev->d_buf; - uint32_t len = dev->d_len; + irqstate_t flags; - if (!wifi_tx_available(priv)) - { - return -ENOBUFS; - } - - ret = esp_wifi_sta_send_data(buffer, len); - if (ret) - { - priv->txrst = len; - if (buffer != priv->txbuf) - { - memcpy(priv->txbuf, buffer, len); - } - - wd_start(&priv->txtimeout, WLAN_TXTOUT, - wlan_txtimeout_expiry, (uint32_t)priv); - - return -EIO; - } - else - { - priv->txrst = 0; - } - - return OK; + flags = enter_critical_section(); + sq_addfirst(&pktbuf->entry, &priv->txb); + leave_critical_section(flags); } /**************************************************************************** * Function: wlan_recvframe * * Description: - * Try to receive RX buffer from RX done buffer queue. + * Try to receive RX packet from RX done packet queue. * * Input Parameters: * priv - Reference to the driver state structure * * Returned Value: - * RX buffer if success or NULl if no buffer in queue. + * RX packet if success or NULl if no packet in queue. * ****************************************************************************/ -static struct wlan_rxbuf *wlan_recvframe(FAR struct wlan_priv_s *priv) +static struct wlan_pktbuf_s *wlan_recvframe(FAR struct wlan_priv_s *priv) { irqstate_t flags; sq_entry_t *entry; - struct wlan_rxbuf *rxbuf = NULL; + struct wlan_pktbuf_s *pktbuf = NULL; flags = enter_critical_section(); entry = sq_remfirst(&priv->rxb); - if (entry) + if (entry != NULL) { - rxbuf = container_of(entry, struct wlan_rxbuf, entry); + pktbuf = container_of(entry, struct wlan_pktbuf_s, entry); } leave_critical_section(flags); - return rxbuf; + 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_s *wlan_txframe(FAR struct wlan_priv_s *priv) +{ + irqstate_t flags; + sq_entry_t *entry; + struct wlan_pktbuf_s *pktbuf = NULL; + + flags = enter_critical_section(); + + entry = sq_remfirst(&priv->txb); + if (entry != NULL) + { + pktbuf = container_of(entry, struct wlan_pktbuf_s, entry); + } + + leave_critical_section(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(FAR struct wlan_priv_s *priv) +{ + struct wlan_pktbuf_s *pktbuf; + int ret; + + while ((pktbuf = wlan_txframe(priv)) != NULL) + { + ret = priv->ops->send(pktbuf->buffer, pktbuf->len); + if (ret < 0) + { + wlan_add_txpkt_head(priv, pktbuf); + wd_start(&priv->txtimeout, WLAN_TXTOUT, + wlan_txtimeout_expiry, (uint32_t)priv); + break; + } + else + { + wlan_free_buffer(priv, pktbuf->buffer); + } + } } /**************************************************************************** @@ -438,21 +550,15 @@ static struct wlan_rxbuf *wlan_recvframe(FAR struct wlan_priv_s *priv) * 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. + * priv - Reference to the driver state structure * * Returned Value: * None * ****************************************************************************/ -static void wlan_tx_done(uint8_t ifidx, uint8_t *data, - uint16_t *len, bool status) +static void wlan_tx_done(FAR struct wlan_priv_s *priv) { - FAR struct wlan_priv_s *priv = &g_wlan_priv; - wd_cancel(&priv->txtimeout); wlan_txavail(&priv->dev); @@ -466,6 +572,7 @@ static void wlan_tx_done(uint8_t ifidx, uint8_t *data, * 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 @@ -475,11 +582,11 @@ static void wlan_tx_done(uint8_t ifidx, uint8_t *data, * ****************************************************************************/ -static int wlan_rx_done(void *buffer, uint16_t len, void *eb) +static int wlan_rx_done(FAR struct wlan_priv_s *priv, void *buffer, + uint16_t len, void *eb) { - struct wlan_rxbuf *rxbuf; + struct wlan_pktbuf_s *pktbuf; irqstate_t flags; - FAR struct wlan_priv_s *priv = &g_wlan_priv; int ret = 0; if (!priv->ifup) @@ -495,23 +602,23 @@ static int wlan_rx_done(void *buffer, uint16_t len, void *eb) goto out; } - rxbuf = wlan_alloc_buffer(priv); - if (!rxbuf) + pktbuf = wlan_alloc_buffer(priv); + if (pktbuf == NULL) { ret = -ENOBUFS; goto out; } - memcpy(rxbuf->buffer, buffer, len); - rxbuf->len = len; + memcpy(pktbuf->buffer, buffer, len); + pktbuf->len = len; - if (eb) + if (eb != NULL) { esp_wifi_free_eb(eb); } flags = enter_critical_section(); - sq_addlast(&rxbuf->entry, &priv->rxb); + sq_addlast(&pktbuf->entry, &priv->rxb); leave_critical_section(flags); if (work_available(&priv->rxwork)) @@ -522,7 +629,7 @@ static int wlan_rx_done(void *buffer, uint16_t len, void *eb) return 0; out: - if (eb) + if (eb != NULL) { esp_wifi_free_eb(eb); } @@ -547,7 +654,7 @@ out: static void wlan_rxpoll(FAR void *arg) { - struct wlan_rxbuf *rxbuf; + struct wlan_pktbuf_s *pktbuf; struct eth_hdr_s *eth_hdr; FAR struct wlan_priv_s *priv = (FAR struct wlan_priv_s *)arg; FAR struct net_driver_s *dev = &priv->dev; @@ -555,19 +662,23 @@ static void wlan_rxpoll(FAR void *arg) 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 ((rxbuf = wlan_recvframe(priv)) != NULL) + while ((pktbuf = wlan_recvframe(priv)) != NULL) { - dev->d_buf = rxbuf->buffer; - dev->d_len = rxbuf->len; + dev->d_buf = pktbuf->buffer; + dev->d_len = pktbuf->len; #ifdef WLAN_RX_THRESHOLD - rbytes += rxbuf->len; + rbytes += pktbuf->len; #endif #ifdef CONFIG_NET_PKT @@ -639,7 +750,7 @@ static void wlan_rxpoll(FAR void *arg) /* And send the packet */ - wlan_transmit(priv); + wlan_cache_txpkt_tail(priv); } } else @@ -677,7 +788,7 @@ static void wlan_rxpoll(FAR void *arg) /* And send the packet */ - wlan_transmit(priv); + wlan_cache_txpkt_tail(priv); } } else @@ -698,7 +809,7 @@ static void wlan_rxpoll(FAR void *arg) if (priv->dev.d_len > 0) { - wlan_transmit(priv); + wlan_cache_txpkt_tail(priv); } } else @@ -737,7 +848,11 @@ static void wlan_rxpoll(FAR void *arg) #endif } - net_unlock(); + /* Try to send all cached TX packets */ + + wlan_transmit(priv); + + net_unlock(); } /**************************************************************************** @@ -748,7 +863,7 @@ static void wlan_rxpoll(FAR void *arg) * packets ready to send. This is a callback from devif_poll(). * devif_poll() may be called: * - * 1. When the preceding TX packet send times out and the interface is + * 1. When the preceding TX packets send times out and the interface is * reset * 2. During normal TX polling * @@ -762,6 +877,7 @@ static void wlan_rxpoll(FAR void *arg) static int wlan_txpoll(FAR struct net_driver_s *dev) { + struct wlan_pktbuf_s *pktbuf; FAR struct wlan_priv_s *priv = (FAR struct wlan_priv_s *)dev->d_private; DEBUGASSERT(dev->d_buf != NULL); @@ -794,11 +910,16 @@ static int wlan_txpoll(FAR struct net_driver_s *dev) } #endif /* CONFIG_NET_IPv6 */ - int ret = wlan_transmit(priv); - if (ret) + wlan_cache_txpkt_tail(priv); + + pktbuf = wlan_alloc_buffer(priv); + if (pktbuf == NULL) { - return -EBUSY; + return -ENOMEM; } + + dev->d_buf = pktbuf->buffer; + dev->d_len = WLAN_BUF_SIZE; } /* If zero is returned, the polling will continue until @@ -830,19 +951,40 @@ static int wlan_txpoll(FAR struct net_driver_s *dev) static void wlan_dopoll(FAR struct wlan_priv_s *priv) { FAR struct net_driver_s *dev = &priv->dev; + struct wlan_pktbuf_s *pktbuf; + uint8_t *txbuf; + int ret; - if (!wifi_tx_available(priv)) + pktbuf = wlan_alloc_buffer(priv); + if (pktbuf == NULL) { return ; } - dev->d_buf = priv->txbuf; + dev->d_buf = pktbuf->buffer; + dev->d_len = WLAN_BUF_SIZE; - /* If so, then poll the network for new XMIT data */ + /* Try to let TCP/IP to send all packets to netcard driver */ - devif_timer(dev, 0, wlan_txpoll); + do + { + txbuf = dev->d_buf; + ret = devif_poll(dev, wlan_txpoll); + } + while ((ret == 0) && + (dev->d_buf != txbuf)); - dev->d_buf = NULL; + if (dev->d_buf != NULL) + { + 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); } /**************************************************************************** @@ -863,6 +1005,10 @@ 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); @@ -925,6 +1071,7 @@ static void wlan_poll_work(FAR void *arg) int32_t delay = WLAN_WDDELAY; FAR struct wlan_priv_s *priv = (FAR struct wlan_priv_s *)arg; struct net_driver_s *dev = &priv->dev; + struct wlan_pktbuf_s *pktbuf; /* Lock the network and serialize driver operations if necessary. * NOTE: Serialization is only required in the case where the driver work @@ -934,30 +1081,41 @@ static void wlan_poll_work(FAR void *arg) net_lock(); - /* Check if there is room in the send another TX packet. We cannot perform + pktbuf = wlan_alloc_buffer(priv); + if (pktbuf == NULL) + { + delay = 1; + goto exit; + } + + dev->d_buf = pktbuf->buffer; + dev->d_len = WLAN_BUF_SIZE; + + /* Check if there is room in the send another TX packets. We cannot perform * the TX poll if he are unable to accept another packet for transmission. * * If there is no room, we should reset the timeout value to be 1 to * trigger the timer as soon as possible. */ - if (!wifi_tx_available(priv)) - { - delay = 1; - goto exit; - } - - dev->d_buf = priv->txbuf; - /* Update TCP timing states and poll the network for new XMIT data. */ devif_timer(&priv->dev, delay, wlan_txpoll); - dev->d_buf = NULL; + if (dev->d_buf != NULL) + { + 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); exit: wd_start(&priv->txpoll, delay, wlan_poll_expiry, (wdparm_t)priv); - net_unlock(); } @@ -1007,6 +1165,10 @@ static void wlan_txavail_work(FAR void *arg) { FAR struct wlan_priv_s *priv = (FAR 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 @@ -1044,6 +1206,7 @@ static void wlan_txavail_work(FAR void *arg) static int wlan_ifup(FAR struct net_driver_s *dev) { + int ret; FAR struct wlan_priv_s *priv = (FAR struct wlan_priv_s *)dev->d_private; #ifdef CONFIG_NET_IPv4 @@ -1066,6 +1229,14 @@ static int wlan_ifup(FAR struct net_driver_s *dev) return OK; } + ret = priv->ops->start(); + if (ret < 0) + { + net_unlock(); + nerr("ERROR: Failed to start Wi-Fi ret=%d\n", ret); + return ret; + } + #ifdef CONFIG_NET_ICMPv6 /* Set up IPv6 multicast address filtering */ @@ -1102,6 +1273,7 @@ static int wlan_ifup(FAR struct net_driver_s *dev) static int wlan_ifdown(FAR struct net_driver_s *dev) { + int ret; FAR struct wlan_priv_s *priv = (FAR struct wlan_priv_s *)dev->d_private; net_lock(); @@ -1121,6 +1293,12 @@ static int wlan_ifdown(FAR struct net_driver_s *dev) priv->ifup = false; + ret = priv->ops->stop(); + if (ret < 0) + { + nerr("ERROR: Failed to stop Wi-Fi ret=%d\n", ret); + } + net_unlock(); return OK; @@ -1305,9 +1483,9 @@ static int wlan_ioctl(FAR struct net_driver_s *dev, unsigned long arg) { int ret; - struct iw_point *essid; - struct iw_encode_ext *ext; struct iwreq *iwr = (struct iwreq *)arg; + struct wlan_priv_s *priv = (struct wlan_priv_s *)dev->d_private; + const struct wlan_ops_s *ops = priv->ops; /* Decode and dispatch the driver-specific IOCTL command */ @@ -1318,8 +1496,8 @@ static int wlan_ioctl(FAR struct net_driver_s *dev, case SIOCMIINOTIFY: /* Set up for PHY event notifications */ { struct mii_ioctl_notify_s *req = (struct mii_ioctl_notify_s *)arg; - ret = esp_wifi_notify_subscribe(req->pid, &req->event); - if (ret) + ret = ops->event(req->pid, &req->event); + if (ret < 0) { nerr("ERROR: Failed to subscribe event\n"); } @@ -1329,43 +1507,182 @@ static int wlan_ioctl(FAR struct net_driver_s *dev, #endif case SIOCSIWENCODEEXT: - { - ext = iwr->u.encoding.pointer; - ret = esp_wifi_set_password(ext->key, ext->key_len); - if (ret) - { - nerr("ERROR: Failed to set password\n"); - } - } - break; - case SIOCSIWESSID: - { - iwr = (struct iwreq *)arg; - essid = &iwr->u.essid; - ret = esp_wifi_set_ssid(essid->pointer, essid->length); - if (ret) - { - nerr("ERROR: Failed to set SSID\n"); - break; - } + ret = ops->passwd(iwr, true); - ret = esp_wifi_connect_internal(); - if (ret) - { - nerr("ERROR: Failed to start connecting\n"); - break; - } - } break; - case SIOCSIWMODE: - ret = OK; + + case SIOCGIWENCODEEXT: + ret = ops->passwd(iwr, false); break; - case SIOCSIWAUTH: - ret = OK; + + 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; + } + +#ifdef ESP32C3_WLAN_HAS_STA + ret = wlan_sta_set_linkstatus(dev, true); + if (ret < 0) + { + nerr("ERROR: Failed to set linkstatus\n"); + break; + } +#endif + } + } + else + { + ret = ops->disconnect(); + if (ret < 0) + { + nerr("ERROR: Failed to disconnect\n"); + break; + } + +#ifdef ESP32C3_WLAN_HAS_STA + ret = wlan_sta_set_linkstatus(dev, false); + if (ret < 0) + { + nerr("ERROR: Failed to set linkstatus\n"); + break; + } +#endif + } + break; - case SIOCSIWFREQ: - ret = OK; + + 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; + } + +#ifdef ESP32C3_WLAN_HAS_STA + ret = wlan_sta_set_linkstatus(dev, true); + if (ret < 0) + { + nerr("ERROR: Failed to set linkstatus\n"); + break; + } +#endif + } + else + { + ret = ops->disconnect(); + if (ret < 0) + { + nerr("ERROR: Failed to disconnect\n"); + break; + } + +#ifdef ESP32C3_WLAN_HAS_STA + ret = wlan_sta_set_linkstatus(dev, false); + if (ret < 0) + { + nerr("ERROR: Failed to set linkstatus\n"); + break; + } +#endif + } + + 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 */ @@ -1383,86 +1700,204 @@ static int wlan_ioctl(FAR struct net_driver_s *dev, * Initialize the ESP32-C3 driver * * Input Parameters: - * devno - The device number. + * devno - The device number + * mac_addr - MAC address * * Returned Value: * OK on success; Negated errno on failure. * ****************************************************************************/ -static int esp32c3_net_initialize(unsigned int devno) +static int esp32c3_net_initialize(int devno, uint8_t *mac_addr, + const struct wlan_ops_s *ops) { int ret; - uint8_t eth_mac[6]; FAR struct wlan_priv_s *priv; + FAR struct net_driver_s *netdev; - /* Get the interface structure associated with this interface number. */ + priv = &g_wlan_priv[devno]; + if (priv->ref != 0) + { + priv->ref++; + return OK; + } - priv = &g_wlan_priv; + netdev = &priv->dev; /* Initialize the driver structure */ memset(priv, 0, sizeof(struct wlan_priv_s)); - priv->dev.d_ifup = wlan_ifup; /* I/F down callback */ - priv->dev.d_ifdown = wlan_ifdown; /* I/F up (new IP address) callback */ - priv->dev.d_txavail = wlan_txavail; /* New TX data callback */ + 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 - priv->dev.d_addmac = wlan_addmac; /* Add multicast MAC address */ - priv->dev.d_rmmac = wlan_rmmac; /* Remove multicast MAC address */ + netdev->d_addmac = wlan_addmac; /* Add multicast MAC address */ + netdev->d_rmmac = wlan_rmmac; /* Remove multicast MAC address */ #endif #ifdef CONFIG_NETDEV_IOCTL - priv->dev.d_ioctl = wlan_ioctl; /* Handle network IOCTL commands */ + netdev->d_ioctl = wlan_ioctl; /* Handle network IOCTL commands */ #endif /* Used to recover private state from dev */ - priv->dev.d_private = (void *)&g_wlan_priv; + netdev->d_private = (void *)priv; - /* Create a watchdog for timing polling for and timing of transmissions */ + memcpy(netdev->d_mac.ether.ether_addr_octet, mac_addr, MAC_LEN); - esp_wifi_sta_read_mac(eth_mac); - - memcpy(priv->dev.d_mac.ether.ether_addr_octet, eth_mac, sizeof(eth_mac)); - - ninfo("%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]); - - /* Put the interface in the down state. */ - - wlan_ifdown(&priv->dev); - - ret = netdev_register(&priv->dev, NET_LL_IEEE80211); - if (ret) + ret = netdev_register(netdev, NET_LL_IEEE80211); + if (ret < 0) { - nerr("ERROR: Initialization of Ethernet block failed: %d\n", ret); + nerr("ERROR: Initialization of IEEE 802.11 block failed: %d\n", ret); return ret; } - ret = esp_wifi_adapter_init(); - if (ret) - { - nerr("ERROR: Initialize Wi-Fi adapter error: %d\n", ret); - netdev_unregister(&priv->dev); - return ret; - } + priv->ops = ops; - ret = esp_wifi_sta_register_recv_cb(wlan_rx_done); - if (ret) - { - DEBUGASSERT(0); - } + priv->ref++; - ret = esp_wifi_sta_register_txdone_cb(wlan_tx_done); - if (ret) - { - DEBUGASSERT(0); - } + 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 ESP32C3_WLAN_HAS_STA +static int wlan_sta_rx_done(void *buffer, uint16_t len, void *eb) +{ + FAR struct wlan_priv_s *priv = &g_wlan_priv[ESP32C3_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: + * 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_sta_tx_done(uint8_t *data, uint16_t *len, bool status) +{ + FAR struct wlan_priv_s *priv = &g_wlan_priv[ESP32C3_WLAN_STA_DEVNO]; + + wlan_tx_done(priv); +} + +/**************************************************************************** + * Name: wlan_sta_set_linkstatus + * + * Description: + * Set Wi-Fi station link status + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * 0:Success; negated errno on failure + * + ****************************************************************************/ + +static int wlan_sta_set_linkstatus(FAR struct net_driver_s *dev, + bool linkstatus) +{ + if (dev) + { + if (linkstatus == true) + { + dev->d_flags |= IFF_RUNNING; + } + else + { + dev->d_flags &= ~IFF_RUNNING; + } + + return OK; + } + + return -EINVAL; +} + +#endif + +/**************************************************************************** + * 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 ESP32C3_WLAN_HAS_SOFTAP +static int wlan_softap_rx_done(void *buffer, uint16_t len, void *eb) +{ + FAR struct wlan_priv_s *priv = &g_wlan_priv[ESP32C3_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) +{ + FAR struct wlan_priv_s *priv = &g_wlan_priv[ESP32C3_WLAN_SOFTAP_DEVNO]; + + wlan_tx_done(priv); +} +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -1481,7 +1916,111 @@ static int esp32c3_net_initialize(unsigned int devno) * ****************************************************************************/ +#ifdef ESP32C3_WLAN_HAS_STA int esp32c3_wlan_sta_initialize(void) { - return esp32c3_net_initialize(WLAN_STA_DEVNO); + 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 = esp32c3_net_initialize(ESP32C3_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 + +/**************************************************************************** + * Name: esp32c3_wlan_softap_initialize + * + * Description: + * Initialize the ESP32-C3 WLAN softAP netcard driver + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success; Negated errno on failure. + * + ****************************************************************************/ + +#ifdef ESP32C3_WLAN_HAS_SOFTAP +int esp32c3_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 = esp32c3_net_initialize(ESP32C3_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 + +#endif /* CONFIG_ESP32C3_WIRELESS */ diff --git a/arch/risc-v/src/esp32c3/esp32c3_wlan.h b/arch/risc-v/src/esp32c3/esp32c3_wlan.h index de93c468a1b..54cdf9ad064 100644 --- a/arch/risc-v/src/esp32c3/esp32c3_wlan.h +++ b/arch/risc-v/src/esp32c3/esp32c3_wlan.h @@ -27,6 +27,8 @@ #include +#include "esp32c3_wifi_adapter.h" + #ifndef __ASSEMBLY__ #undef EXTERN @@ -38,6 +40,8 @@ extern "C" #define EXTERN extern #endif +#ifdef CONFIG_ESP32C3_WIRELESS + /**************************************************************************** * Public Function Prototypes ****************************************************************************/ @@ -56,8 +60,29 @@ extern "C" * ****************************************************************************/ +#ifdef ESP32C3_WLAN_HAS_STA int esp32c3_wlan_sta_initialize(void); +#endif +/**************************************************************************** + * Name: esp32c3_wlan_softap_initialize + * + * Description: + * Initialize the ESP32-C3 WLAN softAP netcard driver + * + * Input Parameters: + * None + * + * Returned Value: + * OK on success; Negated errno on failure. + * + ****************************************************************************/ + +#ifdef ESP32C3_WLAN_HAS_SOFTAP +int esp32c3_wlan_softap_initialize(void); +#endif + +#endif /* CONFIG_ESP32C3_WIRELESS */ #ifdef __cplusplus } #endif diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/configs/sta_softap/defconfig b/boards/risc-v/esp32c3/esp32c3-devkit/configs/sta_softap/defconfig new file mode 100644 index 00000000000..942e6734163 --- /dev/null +++ b/boards/risc-v/esp32c3/esp32c3-devkit/configs/sta_softap/defconfig @@ -0,0 +1,82 @@ +# +# 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_NSH_ARGCAT is not set +# CONFIG_NSH_CMDOPT_HEXDUMP is not set +# CONFIG_NSH_CMDPARMS is not set +CONFIG_ARCH="risc-v" +CONFIG_ARCH_BOARD="esp32c3-devkit" +CONFIG_ARCH_BOARD_ESP32C3_DEVKIT=y +CONFIG_ARCH_CHIP="esp32c3" +CONFIG_ARCH_CHIP_ESP32C3=y +CONFIG_ARCH_CHIP_ESP32C3WROOM02=y +CONFIG_ARCH_INTERRUPTSTACK=1536 +CONFIG_ARCH_RISCV=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BOARD_LOOPSPERMSEC=16717 +CONFIG_BUILTIN=y +CONFIG_DEBUG_ASSERTIONS=y +CONFIG_DEBUG_ERROR=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_WARN=y +CONFIG_DEBUG_WIRELESS=y +CONFIG_DEBUG_WIRELESS_ERROR=y +CONFIG_DRIVERS_IEEE80211=y +CONFIG_DRIVERS_WIRELESS=y +CONFIG_ESP32C3_MTD_OFFSET=0x110000 +CONFIG_ESP32C3_MTD_SIZE=0xf0000 +CONFIG_ESP32C3_SPIFLASH=y +CONFIG_ESP32C3_WIFI_SAVE_PARAM=y +CONFIG_ESP32C3_WIFI_STATION_SOFTAP_COEXISTENCE=y +CONFIG_ESP32C3_WIRELESS=y +CONFIG_EXAMPLES_DHCPD=y +CONFIG_EXPERIMENTAL=y +CONFIG_FS_PROCFS=y +CONFIG_FS_SPIFFS=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_IDLETHREAD_STACKSIZE=3072 +CONFIG_INTELHEX_BINARY=y +CONFIG_LIBC_FLOATINGPOINT=y +CONFIG_MAX_TASKS=16 +CONFIG_MM_REGIONS=3 +CONFIG_NETDB_DNSCLIENT=y +CONFIG_NETDEV_LATEINIT=y +CONFIG_NETDEV_PHY_IOCTL=y +CONFIG_NETDEV_WIRELESS_IOCTL=y +CONFIG_NETUTILS_DHCPD=y +CONFIG_NET_BROADCAST=y +CONFIG_NET_ETH_PKTSIZE=1514 +CONFIG_NET_ICMP=y +CONFIG_NET_ICMP_SOCKET=y +CONFIG_NET_SOCKOPTS=y +CONFIG_NET_UDP=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_LINELEN=64 +CONFIG_NSH_READLINE=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_PTHREAD_MUTEX_TYPES=y +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_LPWORK=y +CONFIG_SCHED_WAITPID=y +CONFIG_SDCLONE_DISABLE=y +CONFIG_SIG_DEFAULT=y +CONFIG_SPIFFS_NAME_MAX=48 +CONFIG_START_DAY=6 +CONFIG_START_MONTH=12 +CONFIG_START_YEAR=2011 +CONFIG_SYSTEM_DHCPC_RENEW=y +CONFIG_SYSTEM_NSH=y +CONFIG_SYSTEM_PING=y +CONFIG_UART0_SERIAL_CONSOLE=y +CONFIG_USER_ENTRYPOINT="nsh_main" +CONFIG_WIRELESS=y +CONFIG_WIRELESS_WAPI=y +CONFIG_WIRELESS_WAPI_CMDTOOL=y diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/configs/wapi/defconfig b/boards/risc-v/esp32c3/esp32c3-devkit/configs/wapi/defconfig index 5ba6b7befa9..3fb338c699a 100644 --- a/boards/risc-v/esp32c3/esp32c3-devkit/configs/wapi/defconfig +++ b/boards/risc-v/esp32c3/esp32c3-devkit/configs/wapi/defconfig @@ -27,6 +27,7 @@ CONFIG_HAVE_CXX=y CONFIG_HAVE_CXXINITIALIZE=y CONFIG_IDLETHREAD_STACKSIZE=3072 CONFIG_INTELHEX_BINARY=y +CONFIG_LIBC_FLOATINGPOINT=y CONFIG_NAME_MAX=48 CONFIG_NETDB_DNSCLIENT=y CONFIG_NETDEV_LATEINIT=y diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_bringup.c b/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_bringup.c index e0b11e9c7b5..95f324849b6 100644 --- a/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_bringup.c +++ b/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_bringup.c @@ -38,7 +38,8 @@ #include #include "esp32c3_wlan.h" - +#include "esp32c3_spiflash.h" +#include "esp32c3_partition.h" #include "esp32c3-devkit.h" /**************************************************************************** @@ -49,6 +50,46 @@ * Public Functions ****************************************************************************/ +/**************************************************************************** + * Name: esp32c3_init_wifi_storage + * + * Description: + * Initialization of saved Wi-Fi parameters + * + ****************************************************************************/ + +#ifdef CONFIG_ESP32C3_WIFI_SAVE_PARAM +static int esp32c3_init_wifi_storage(void) +{ + int ret; + const char *path = "/dev/mtdblock1"; + FAR struct mtd_dev_s *mtd_part; + + mtd_part = esp32c3_spiflash_alloc_mtdpart(); + if (!mtd_part) + { + syslog(LOG_ERR, "ERROR: Failed to alloc MTD partition of SPI Flash\n"); + return -1; + } + + ret = register_mtddriver(path, mtd_part, 0777, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to register MTD: %d\n", ret); + return -1; + } + + ret = nx_mount(path, CONFIG_ESP32C3_WIFI_FS_MOUNTPT, "spiffs", 0, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to mount the FS volume: %d\n", ret); + return ret; + } + + return 0; +} +#endif + /**************************************************************************** * Name: esp32c3_bringup * @@ -165,12 +206,36 @@ int esp32c3_bringup(void) #endif #ifdef CONFIG_ESP32C3_WIRELESS + +#ifdef CONFIG_ESP32C3_WIFI_SAVE_PARAM + ret = esp32c3_init_wifi_storage(); + if (ret) + { + syslog(LOG_ERR, "ERROR: Failed to initialize Wi-Fi storage\n"); + return ret; + } +#endif + +#ifdef CONFIG_NET +#ifdef ESP32C3_WLAN_HAS_STA ret = esp32c3_wlan_sta_initialize(); if (ret) { - syslog(LOG_ERR, "ERROR: Failed to initialize Wi-Fi\n"); + syslog(LOG_ERR, "ERROR: Failed to initialize Wi-Fi station\n"); return ret; } +#endif + +#ifdef ESP32C3_WLAN_HAS_SOFTAP + ret = esp32c3_wlan_softap_initialize(); + if (ret) + { + syslog(LOG_ERR, "ERROR: Failed to initialize Wi-Fi softAP\n"); + return ret; + } +#endif +#endif + #endif /* If we got here then perhaps not all initialization was successful, but