From dbced75b48d2fed969e4ee430a50cadf858eb4bf Mon Sep 17 00:00:00 2001 From: Glenn Moloney Date: Sat, 1 Jul 2023 13:54:44 +1000 Subject: [PATCH] esp32/network_wlan: Wait for STA/AP START/STOP event in wlan.active. This is a fix for commit bccbaa92b1fc6237f0f49a7f07cc194835fbf4e3: - Should only wait for WIFI_EVENT_STA_START when invoked on the STA_IF interface. - The WIFI_EVENT_STA_START event is generated every time the STA_IF interface is set active(True) and it was previously inactive, ie. not only after calling esp_wifi_start(). - Also wait for WIFI_EVENT_STA_STOP when deactivating the interface. - Also wait for relevant AP events. Fixes issue #11910. Signed-off-by: Glenn Moloney Signed-off-by: Damien George --- ports/esp32/modnetwork.h | 1 + ports/esp32/network_lan.c | 15 +++++++-------- ports/esp32/network_wlan.c | 29 ++++++++++++++++++++++------- 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/ports/esp32/modnetwork.h b/ports/esp32/modnetwork.h index b1b3fc368a..79bf9973ca 100644 --- a/ports/esp32/modnetwork.h +++ b/ports/esp32/modnetwork.h @@ -44,6 +44,7 @@ typedef struct _base_if_obj_t { mp_obj_base_t base; esp_interface_t if_id; esp_netif_t *netif; + volatile bool active; } base_if_obj_t; extern const mp_obj_type_t esp_network_wlan_type; diff --git a/ports/esp32/network_lan.c b/ports/esp32/network_lan.c index 8128eb5e11..fe3ff6f772 100644 --- a/ports/esp32/network_lan.c +++ b/ports/esp32/network_lan.c @@ -48,7 +48,6 @@ typedef struct _lan_if_obj_t { base_if_obj_t base; bool initialized; - bool active; int8_t mdc_pin; int8_t mdio_pin; int8_t phy_power_pin; @@ -295,7 +294,7 @@ STATIC mp_obj_t get_lan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar esp_err_t esp_err = esp_eth_driver_install(&config, &self->eth_handle); if (esp_err == ESP_OK) { - self->active = false; + self->base.active = false; self->initialized = true; } else { if (esp_err == ESP_ERR_INVALID_ARG) { @@ -322,19 +321,19 @@ STATIC mp_obj_t lan_active(size_t n_args, const mp_obj_t *args) { if (n_args > 1) { if (mp_obj_is_true(args[1])) { - self->active = (esp_eth_start(self->eth_handle) == ESP_OK); - if (!self->active) { + self->base.active = (esp_eth_start(self->eth_handle) == ESP_OK); + if (!self->base.active) { mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("ethernet enable failed")); } } else { - self->active = !(esp_eth_stop(self->eth_handle) == ESP_OK); - if (self->active) { + self->base.active = !(esp_eth_stop(self->eth_handle) == ESP_OK); + if (self->base.active) { mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("ethernet disable failed")); } } } - return mp_obj_new_bool(self->active); + return mp_obj_new_bool(self->base.active); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(lan_active_obj, 1, 2, lan_active); @@ -345,7 +344,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(lan_status_obj, lan_status); STATIC mp_obj_t lan_isconnected(mp_obj_t self_in) { lan_if_obj_t *self = MP_OBJ_TO_PTR(self_in); - return self->active ? mp_obj_new_bool(self->phy->get_link(self->phy) == ETH_LINK_UP) : mp_const_false; + return self->base.active ? mp_obj_new_bool(self->phy->get_link(self->phy) == ETH_LINK_UP) : mp_const_false; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(lan_isconnected_obj, lan_isconnected); diff --git a/ports/esp32/network_wlan.c b/ports/esp32/network_wlan.c index 3c88f8db86..8287731c31 100644 --- a/ports/esp32/network_wlan.c +++ b/ports/esp32/network_wlan.c @@ -76,7 +76,7 @@ static bool mdns_initialised = false; #endif static uint8_t conf_wifi_sta_reconnects = 0; -static volatile uint8_t wifi_sta_reconnects; +static uint8_t wifi_sta_reconnects; // This function is called by the system-event task and so runs in a different // thread to the main MicroPython task. It must not raise any Python exceptions. @@ -84,9 +84,14 @@ static void network_wlan_wifi_event_handler(void *event_handler_arg, esp_event_b switch (event_id) { case WIFI_EVENT_STA_START: ESP_LOGI("wifi", "STA_START"); + wlan_sta_obj.active = true; wifi_sta_reconnects = 0; break; + case WIFI_EVENT_STA_STOP: + wlan_sta_obj.active = false; + break; + case WIFI_EVENT_STA_CONNECTED: ESP_LOGI("network", "CONNECTED"); break; @@ -140,6 +145,15 @@ static void network_wlan_wifi_event_handler(void *event_handler_arg, esp_event_b } break; } + + case WIFI_EVENT_AP_START: + wlan_ap_obj.active = true; + break; + + case WIFI_EVENT_AP_STOP: + wlan_ap_obj.active = false; + break; + default: break; } @@ -184,10 +198,12 @@ void esp_initialise_wifi(void) { wlan_sta_obj.base.type = &esp_network_wlan_type; wlan_sta_obj.if_id = ESP_IF_WIFI_STA; wlan_sta_obj.netif = esp_netif_create_default_wifi_sta(); + wlan_sta_obj.active = false; wlan_ap_obj.base.type = &esp_network_wlan_type; wlan_ap_obj.if_id = ESP_IF_WIFI_AP; wlan_ap_obj.netif = esp_netif_create_default_wifi_ap(); + wlan_ap_obj.active = false; wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_LOGD("modnetwork", "Initializing WiFi"); @@ -237,16 +253,15 @@ STATIC mp_obj_t network_wlan_active(size_t n_args, const mp_obj_t *args) { } else { esp_exceptions(esp_wifi_set_mode(mode)); if (!wifi_started) { - // WIFI_EVENT_STA_START must be received before esp_wifi_connect() can be called. - // Use the `wifi_sta_reconnects` variable to detect that event. - wifi_sta_reconnects = 1; esp_exceptions(esp_wifi_start()); wifi_started = true; - while (wifi_sta_reconnects != 0) { - MICROPY_EVENT_POLL_HOOK; - } } } + + // Wait for the interface to be in the correct state. + while (self->active != active) { + MICROPY_EVENT_POLL_HOOK; + } } return (mode & bit) ? mp_const_true : mp_const_false;