diff --git a/arch/xtensa/src/esp32/esp32_wifi_adapter.c b/arch/xtensa/src/esp32/esp32_wifi_adapter.c index 958125cbd1..f571fdd142 100644 --- a/arch/xtensa/src/esp32/esp32_wifi_adapter.c +++ b/arch/xtensa/src/esp32/esp32_wifi_adapter.c @@ -406,7 +406,12 @@ static bool g_sta_connected; /* Wi-Fi station TX done callback function */ static wifi_txdone_cb_t g_sta_txdone_cb; -#endif + +/* Wi-Fi interface configuration */ + +static wifi_config_t g_sta_wifi_cfg; + +#endif /* ESP32_WLAN_HAS_STA */ #ifdef ESP32_WLAN_HAS_SOFTAP @@ -417,7 +422,12 @@ static bool g_softap_started; /* Wi-Fi SoftAP TX done callback function */ static wifi_txdone_cb_t g_softap_txdone_cb; -#endif + +/* Wi-Fi interface configuration */ + +static wifi_config_t g_softap_wifi_cfg; + +#endif /* ESP32_WLAN_HAS_SOFTAP */ /* Device specific lock */ @@ -2222,6 +2232,13 @@ static void esp_evt_work_cb(void *arg) if (ret) { wlerr("Failed to close PS\n"); + break; + } + + ret = esp_wifi_get_config(WIFI_IF_STA, &g_sta_wifi_cfg); + if (ret) + { + wlerr("Failed to get Wi-Fi config data ret=%d\n", ret); } break; @@ -2252,6 +2269,11 @@ static void esp_evt_work_cb(void *arg) #ifdef ESP32_WLAN_HAS_SOFTAP case WIFI_ADPT_EVT_AP_START: wlinfo("INFO: Wi-Fi softap start\n"); + ret = esp_wifi_get_config(WIFI_IF_AP, &g_softap_wifi_cfg); + if (ret) + { + wlerr("Failed to get Wi-Fi config data ret=%d\n", ret); + } break; case WIFI_ADPT_EVT_AP_STOP: @@ -2265,7 +2287,7 @@ static void esp_evt_work_cb(void *arg) case WIFI_ADPT_EVT_AP_STADISCONNECTED: wlinfo("INFO: Wi-Fi station leave\n"); break; -#endif +#endif /* ESP32_WLAN_HAS_SOFTAP */ default: break; } @@ -3475,10 +3497,14 @@ static void *esp_malloc_internal(size_t size) return xtensa_imm_malloc(size); #else void *ptr = kmm_malloc(size); - if (esp32_ptr_extram(ptr)) + + if (ptr != NULL) { - kmm_free(ptr); - return NULL; + if (esp32_ptr_extram(ptr)) + { + kmm_free(ptr); + return NULL; + } } return ptr; @@ -3559,10 +3585,13 @@ static void *esp_calloc_internal(size_t n, size_t size) return xtensa_imm_calloc(n, size); #else void *ptr = kmm_calloc(n, size); - if (esp32_ptr_extram(ptr)) + if (ptr != NULL) { - kmm_free(ptr); - return NULL; + if (esp32_ptr_extram(ptr)) + { + kmm_free(ptr); + return NULL; + } } return ptr; @@ -3591,10 +3620,13 @@ static void *esp_zalloc_internal(size_t size) return xtensa_imm_zalloc(size); #else void *ptr = kmm_zalloc(size); - if (esp32_ptr_extram(ptr)) + if (ptr != NULL) { - kmm_free(ptr); - return NULL; + if (esp32_ptr_extram(ptr)) + { + kmm_free(ptr); + return NULL; + } } return ptr; @@ -5073,27 +5105,45 @@ int esp_wifi_sta_password(struct iwreq *iwr, bool set) return -EINVAL; } - ret = esp_wifi_get_config(WIFI_IF_STA, &wifi_cfg); - if (ret) - { - wlerr("Failed to get Wi-Fi config data ret=%d\n", ret); - return wifi_errno_trans(ret); - } + wifi_cfg = g_sta_wifi_cfg; if (set) { memset(wifi_cfg.sta.password, 0x0, PWD_MAX_LEN); - memcpy(wifi_cfg.sta.password, pdata, len); + + if (ext->alg != IW_ENCODE_ALG_NONE) + { + memcpy(wifi_cfg.sta.password, pdata, len); + } wifi_cfg.sta.pmf_cfg.capable = true; wifi_cfg.sta.listen_interval = DEFAULT_LISTEN_INTERVAL; - ret = esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg); - if (ret) + if (g_sta_connected) { - wlerr("Failed to set Wi-Fi config data ret=%d\n", ret); - return wifi_errno_trans(ret); + ret = esp_wifi_sta_disconnect(); + if (ret) + { + wlerr("Failed to disconnect from Wi-Fi AP ret=%d\n", ret); + return ret; + } + + ret = esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg); + if (ret) + { + wlerr("Failed to set Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + ret = esp_wifi_sta_connect(); + if (ret) + { + wlerr("Failed to connect to Wi-Fi AP ret=%d\n", ret); + return ret; + } } + + g_sta_wifi_cfg = wifi_cfg; } else { @@ -5198,24 +5248,38 @@ int esp_wifi_sta_essid(struct iwreq *iwr, bool set) return -EINVAL; } - ret = esp_wifi_get_config(WIFI_IF_STA, &wifi_cfg); - if (ret) - { - wlerr("Failed to get Wi-Fi config data ret=%d\n", ret); - return wifi_errno_trans(ret); - } + wifi_cfg = g_sta_wifi_cfg; if (set) { memset(wifi_cfg.sta.ssid, 0x0, SSID_MAX_LEN); memcpy(wifi_cfg.sta.ssid, pdata, len); - ret = esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg); - if (ret) + if (g_sta_connected) { - wlerr("Failed to set Wi-Fi config data ret=%d\n", ret); - return wifi_errno_trans(ret); + ret = esp_wifi_sta_disconnect(); + if (ret) + { + wlerr("Failed to disconnect from Wi-Fi AP ret=%d\n", ret); + return ret; + } + + ret = esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg); + if (ret) + { + wlerr("Failed to set Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + ret = esp_wifi_sta_connect(); + if (ret) + { + wlerr("Failed to connect to Wi-Fi AP ret=%d\n", ret); + return ret; + } } + + g_sta_wifi_cfg = wifi_cfg; } else { @@ -5272,27 +5336,41 @@ int esp_wifi_sta_bssid(struct iwreq *iwr, bool set) struct sockaddr *sockaddr; char *pdata; - ret = esp_wifi_get_config(WIFI_IF_STA, &wifi_cfg); - if (ret) - { - wlerr("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; + wifi_cfg = g_sta_wifi_cfg; + if (set) { wifi_cfg.sta.bssid_set = true; memcpy(wifi_cfg.sta.bssid, pdata, MAC_LEN); - ret = esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg); - if (ret) + if (g_sta_connected) { - wlerr("Failed to set Wi-Fi config data ret=%d\n", ret); - return wifi_errno_trans(ret); + ret = esp_wifi_sta_disconnect(); + if (ret) + { + wlerr("Failed to disconnect from Wi-Fi AP ret=%d\n", ret); + return ret; + } + + ret = esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg); + if (ret) + { + wlerr("Failed to set Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + ret = esp_wifi_sta_connect(); + if (ret) + { + wlerr("Failed to connect to Wi-Fi AP ret=%d\n", ret); + return ret; + } } + + g_sta_wifi_cfg = wifi_cfg; } else { @@ -5333,6 +5411,13 @@ int esp_wifi_sta_connect(void) g_sta_reconnect = true; + ret = esp_wifi_set_config(WIFI_IF_STA, &g_sta_wifi_cfg); + if (ret) + { + wlerr("Failed to set Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + ret = esp_wifi_connect(); if (ret) { @@ -5454,11 +5539,114 @@ int esp_wifi_sta_auth(struct iwreq *iwr, bool set) { int ret; int cmd; + wifi_config_t wifi_cfg; wifi_ap_record_t ap_info; + wifi_cfg = g_sta_wifi_cfg; + if (set) { - return OK; + cmd = iwr->u.param.flags & IW_AUTH_INDEX; + switch (cmd) + { + case IW_AUTH_WPA_VERSION: + { + switch (iwr->u.param.value) + { + case IW_AUTH_WPA_VERSION_DISABLED: + wifi_cfg.sta.threshold.authmode = WIFI_AUTH_OPEN; + break; + + case IW_AUTH_WPA_VERSION_WPA: + wifi_cfg.sta.threshold.authmode = WIFI_AUTH_WPA_PSK; + break; + + case IW_AUTH_WPA_VERSION_WPA2: + wifi_cfg.sta.threshold.authmode = WIFI_AUTH_WPA2_PSK; + break; + + default: + wlerr("Invalid wpa version %" PRId32 "\n", + iwr->u.param.value); + return -EINVAL; + } + } + + break; + case IW_AUTH_CIPHER_PAIRWISE: + case IW_AUTH_CIPHER_GROUP: + { + switch (iwr->u.param.value) + { + case IW_AUTH_CIPHER_NONE: + wifi_cfg.sta.threshold.authmode = WIFI_AUTH_OPEN; + break; + + case IW_AUTH_CIPHER_WEP40: + case IW_AUTH_CIPHER_WEP104: + wifi_cfg.sta.threshold.authmode = WIFI_AUTH_WEP; + break; + + case IW_AUTH_CIPHER_TKIP: + wifi_cfg.sta.threshold.authmode = WIFI_AUTH_WPA_PSK; + break; + + case IW_AUTH_CIPHER_CCMP: + case IW_AUTH_CIPHER_AES_CMAC: + wifi_cfg.sta.threshold.authmode = WIFI_AUTH_WPA2_PSK; + break; + + default: + wlerr("Invalid cipher mode %" PRId32 "\n", + iwr->u.param.value); + return -EINVAL; + } + } + + break; + case IW_AUTH_KEY_MGMT: + case IW_AUTH_TKIP_COUNTERMEASURES: + case IW_AUTH_DROP_UNENCRYPTED: + case IW_AUTH_80211_AUTH_ALG: + case IW_AUTH_WPA_ENABLED: + case IW_AUTH_RX_UNENCRYPTED_EAPOL: + case IW_AUTH_ROAMING_CONTROL: + case IW_AUTH_PRIVACY_INVOKED: + default: + wlerr("Unknown cmd %d\n", cmd); + return -EINVAL; + } + + size_t password_len = strlen((const char *)wifi_cfg.sta.password); + wifi_auth_mode_t authmode = wifi_cfg.sta.threshold.authmode; + + if (g_sta_connected && + ((password_len > 0 && authmode != WIFI_AUTH_OPEN) || + (password_len == 0 && authmode == WIFI_AUTH_OPEN))) + { + ret = esp_wifi_sta_disconnect(); + if (ret) + { + wlerr("Failed to disconnect from Wi-Fi AP ret=%d\n", ret); + return ret; + } + + ret = esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg); + if (ret) + { + wlerr("Failed to set Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + ret = esp_wifi_sta_connect(); + if (ret) + { + wlerr("Failed to connect to Wi-Fi AP ret=%d\n", ret); + return ret; + } + } + + g_sta_wifi_cfg = wifi_cfg; } else { @@ -5526,24 +5714,38 @@ int esp_wifi_sta_auth(struct iwreq *iwr, bool set) int esp_wifi_sta_freq(struct iwreq *iwr, bool set) { int ret; - wifi_config_t wifi_cfg; if (set && (iwr->u.freq.flags == IW_FREQ_FIXED)) { - ret = esp_wifi_get_config(WIFI_IF_STA, &wifi_cfg); - if (ret) - { - wlerr("Failed to get Wi-Fi config data ret=%d\n", ret); - return wifi_errno_trans(ret); - } + wifi_config_t wifi_cfg = g_sta_wifi_cfg; wifi_cfg.sta.channel = esp_freq_to_channel(iwr->u.freq.m); - ret = esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg); - if (ret) + + if (g_sta_connected) { - wlerr("Failed to set Wi-Fi config data ret=%d\n", ret); - return wifi_errno_trans(ret); + ret = esp_wifi_sta_disconnect(); + if (ret) + { + wlerr("Failed to disconnect from Wi-Fi AP ret=%d\n", ret); + return ret; + } + + ret = esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg); + if (ret) + { + wlerr("Failed to set Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + + ret = esp_wifi_sta_connect(); + if (ret) + { + wlerr("Failed to connect to Wi-Fi AP ret=%d\n", ret); + return ret; + } } + + g_sta_wifi_cfg = wifi_cfg; } else { @@ -6142,36 +6344,60 @@ int esp_wifi_softap_password(struct iwreq *iwr, bool set) return -EINVAL; } - ret = esp_wifi_get_config(WIFI_IF_AP, &wifi_cfg); - if (ret) - { - wlerr("Failed to get Wi-Fi config data ret=%d\n", ret); - return wifi_errno_trans(ret); - } - - ext = iwr->u.encoding.pointer; pdata = ext->key; len = ext->key_len; + wifi_cfg = g_softap_wifi_cfg; + if (set) { /* Clear the password field and copy the user password to it */ memset(wifi_cfg.ap.password, 0x0, PWD_MAX_LEN); - memcpy(wifi_cfg.ap.password, pdata, len); - - /* Enable the WPA2 password by default */ - - wifi_cfg.ap.authmode = WIFI_AUTH_WPA_WPA2_PSK; - - /* Setup the config to the SoftAP */ - - ret = esp_wifi_set_config(WIFI_IF_AP, &wifi_cfg); - if (ret) + if (len) { - wlerr("Failed to set Wi-Fi config data ret=%d\n", ret); - return wifi_errno_trans(ret); + memcpy(wifi_cfg.ap.password, pdata, len); + switch (ext->alg) + { + case IW_ENCODE_ALG_NONE: + wifi_cfg.ap.authmode = WIFI_AUTH_OPEN; + break; + + case IW_ENCODE_ALG_WEP: + wifi_cfg.ap.authmode = WIFI_AUTH_WEP; + break; + + case IW_ENCODE_ALG_TKIP: + wifi_cfg.ap.authmode = WIFI_AUTH_WPA_PSK; + break; + + case IW_ENCODE_ALG_CCMP: + wifi_cfg.ap.authmode = WIFI_AUTH_WPA2_PSK; + break; + + case IW_ENCODE_ALG_PMK: + case IW_ENCODE_ALG_AES_CMAC: + wifi_cfg.ap.authmode = WIFI_AUTH_WPA_WPA2_PSK; + break; + + default: + wlerr("Failed to transfer wireless authmode: %d", + ext->alg); + return -EINVAL; + } } + + if (g_softap_started) + { + ret = esp_wifi_set_config(WIFI_IF_AP, &wifi_cfg); + if (ret) + { + wlerr("Failed to set Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + } + + g_softap_wifi_cfg = wifi_cfg; } else { @@ -6234,24 +6460,25 @@ int esp_wifi_softap_essid(struct iwreq *iwr, bool set) return -EINVAL; } - ret = esp_wifi_get_config(WIFI_IF_AP, &wifi_cfg); - if (ret) - { - wlerr("Failed to get Wi-Fi config data ret=%d\n", ret); - return wifi_errno_trans(ret); - } + wifi_cfg = g_softap_wifi_cfg; if (set) { memset(wifi_cfg.ap.ssid, 0x0, SSID_MAX_LEN); memcpy(wifi_cfg.ap.ssid, pdata, len); + wifi_cfg.ap.ssid_len = len; - ret = esp_wifi_set_config(WIFI_IF_AP, &wifi_cfg); - if (ret) + if (g_softap_started) { - wlerr("Failed to set Wi-Fi config data ret=%d\n", ret); - return wifi_errno_trans(ret); + ret = esp_wifi_set_config(WIFI_IF_AP, &wifi_cfg); + if (ret) + { + wlerr("Failed to set Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } } + + g_softap_wifi_cfg = wifi_cfg; } else { @@ -6314,6 +6541,15 @@ int esp_wifi_softap_bssid(struct iwreq *iwr, bool set) int esp_wifi_softap_connect(void) { + int ret; + + ret = esp_wifi_set_config(WIFI_IF_AP, &g_softap_wifi_cfg); + if (ret) + { + wlerr("Failed to set Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } + return OK; } @@ -6384,15 +6620,10 @@ int esp_wifi_softap_auth(struct iwreq *iwr, bool set) int cmd; wifi_config_t wifi_cfg; + wifi_cfg = g_softap_wifi_cfg; + if (set) { - ret = esp_wifi_get_config(WIFI_IF_AP, &wifi_cfg); - if (ret) - { - wlerr("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) { @@ -6464,12 +6695,21 @@ int esp_wifi_softap_auth(struct iwreq *iwr, bool set) return -EINVAL; } - ret = esp_wifi_set_config(WIFI_IF_AP, &wifi_cfg); - if (ret) + size_t password_len = strlen((const char *)wifi_cfg.ap.password); + + if (g_softap_started && + ((password_len > 0 && wifi_cfg.ap.authmode != WIFI_AUTH_OPEN) || + (password_len == 0 && wifi_cfg.ap.authmode == WIFI_AUTH_OPEN))) { - wlerr("Failed to set Wi-Fi config data ret=%d\n", ret); - return wifi_errno_trans(ret); + ret = esp_wifi_set_config(WIFI_IF_AP, &wifi_cfg); + if (ret) + { + wlerr("Failed to set Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } } + + g_softap_wifi_cfg = wifi_cfg; } else { @@ -6500,12 +6740,7 @@ int esp_wifi_softap_freq(struct iwreq *iwr, bool set) int ret; wifi_config_t wifi_cfg; - ret = esp_wifi_get_config(WIFI_IF_AP, &wifi_cfg); - if (ret) - { - wlerr("Failed to get Wi-Fi config data ret=%d\n", ret); - return wifi_errno_trans(ret); - } + wifi_cfg = g_softap_wifi_cfg; if (set) { @@ -6513,12 +6748,17 @@ int esp_wifi_softap_freq(struct iwreq *iwr, bool set) wifi_cfg.ap.channel = channel; - ret = esp_wifi_set_config(WIFI_IF_AP, &wifi_cfg); - if (ret) + if (g_softap_started) { - wlerr("Failed to set Wi-Fi config data ret=%d\n", ret); - return wifi_errno_trans(ret); + ret = esp_wifi_set_config(WIFI_IF_AP, &wifi_cfg); + if (ret) + { + wlerr("Failed to set Wi-Fi config data ret=%d\n", ret); + return wifi_errno_trans(ret); + } } + + g_softap_wifi_cfg = wifi_cfg; } else {