From 1e1d5601dea1c2a5fe04933ec269299536f86b85 Mon Sep 17 00:00:00 2001 From: Kapil Gupta Date: Wed, 24 Sep 2025 10:22:52 +0530 Subject: [PATCH] refactor(esp_wifi): Remove WPS task code --- components/esp_wifi/Kconfig | 8 + components/wpa_supplicant/CMakeLists.txt | 4 +- .../esp_supplicant/src/esp_wps.c | 1277 ++++++----------- .../esp_supplicant/src/esp_wps_i.h | 32 +- examples/wifi/wps/main/wps.c | 176 +-- 5 files changed, 554 insertions(+), 943 deletions(-) diff --git a/components/esp_wifi/Kconfig b/components/esp_wifi/Kconfig index 1a904702eb..c807cd3a73 100644 --- a/components/esp_wifi/Kconfig +++ b/components/esp_wifi/Kconfig @@ -814,6 +814,14 @@ menu "Wi-Fi" be shared to other devices, making it in readable format increases that risk, also passphrase requires pbkdf2 to convert in psk. + config ESP_WIFI_WPS_RECONNECT_ON_FAIL + bool "Reconnect to previous SSID if WPS failed" + default n + help + Select this option to enable reconnection to previous SSID if WPS fails. + This option will only work if station was connected to a network + when WPS was started. + endmenu # "WPS Configuration Options" diff --git a/components/wpa_supplicant/CMakeLists.txt b/components/wpa_supplicant/CMakeLists.txt index eeddfa3493..cafc14a27b 100644 --- a/components/wpa_supplicant/CMakeLists.txt +++ b/components/wpa_supplicant/CMakeLists.txt @@ -264,7 +264,6 @@ target_compile_definitions(${COMPONENT_LIB} PRIVATE EAP_PEAP USE_WPA2_TASK CONFIG_WPS - USE_WPS_TASK ESPRESSIF_USE CONFIG_ECC CONFIG_IEEE80211W @@ -291,6 +290,9 @@ endif() if(CONFIG_ESP_WIFI_WPS_STRICT) target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_WPS_STRICT) endif() +if(CONFIG_ESP_WIFI_WPS_RECONNECT_ON_FAIL) + target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_WPS_RECONNECT_ON_FAIL) +endif() if(CONFIG_ESP_WIFI_SUITE_B_192) target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_SUITEB192) endif() diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_wps.c b/components/wpa_supplicant/esp_supplicant/src/esp_wps.c index 933235270a..186571237a 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wps.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wps.c @@ -4,6 +4,18 @@ * SPDX-License-Identifier: Apache-2.0 */ +/* + This file implements the WPS Enrollee logic, which allows an ESP device to connect + to a WPS-enabled Access Point using either the Push-Button Configuration (PBC) or + PIN method. It handles the WPS state machine, EAPOL frame exchange, and credential + reception. + + The implementation relies on a global state machine (gWpsSm) and interacts with the + main Wi-Fi task via an event loop (eloop). Public API functions are provided to + enable, disable, and start the WPS process, with mutexes ensuring thread safety + at the API boundary. +*/ + #include #include @@ -31,221 +43,47 @@ #include "eap_common/eap_wsc_common.h" #include "esp_wpas_glue.h" +#ifdef CONFIG_WPS_RECONNECT_ON_FAIL +static wifi_config_t *s_previous_wifi_config = NULL; +#endif + +// WPS Timeout Constants (in seconds) +static const int WPS_TOTAL_TIMEOUT_SECS = 120; +static const int WPS_CONNECT_TIMEOUT_SECS = 20; +static const int EAPOL_START_HANDLE_TIMEOUT_SECS = 3; +static const int WPS_MSG_TIMEOUT_M2_SECS = 20; +static const int WPS_MSG_TIMEOUT_FINISH_SECS = 5; +static const int WPS_POST_M8_WORKAROUND_SECS = 2; +static const int WPS_SUCCESS_EVENT_TIMEOUT_SECS = 1; +static const int WPS_SCAN_RETRY_TIMEOUT_SECS = 2; + +// Callback structure for handling WPS events within the Wi-Fi task +static struct wps_sm_funcs *s_wps_sm_cb = NULL; + const char *wps_model_number = CONFIG_IDF_TARGET; +/* API lock to ensure thread safety for public WPS functions */ void *s_wps_api_lock = NULL; /* Used in WPS/WPS-REG public API only, never be freed */ void *s_wps_api_sem = NULL; /* Sync semaphore used between WPS/WPS-REG public API caller task and WPS task, never be freed */ +/* Synchronous flag to indicate if the WPS feature is enabled by the user. Protected by s_wps_api_lock. */ bool s_wps_enabled = false; -#ifdef USE_WPS_TASK -struct wps_rx_param { - u8 sa[ETH_ALEN]; - u8 *buf; - int len; - STAILQ_ENTRY(wps_rx_param) bqentry; -}; -static STAILQ_HEAD(, wps_rx_param) s_wps_rxq; +static void wifi_wps_scan_done(void *arg, ETS_STATUS status); -static struct wps_sm_funcs *s_wps_sm_cb = NULL; -static void *s_wps_task_hdl = NULL; -static void *s_wps_queue = NULL; -static void *s_wps_data_lock = NULL; -static void *s_wps_task_create_sem = NULL; -static uint8_t s_wps_sig_cnt[SIG_WPS_NUM] = {0}; - -#endif - -void wifi_wps_scan_done(void *arg, ETS_STATUS status); -void wifi_wps_scan(void *data, void *user_ctx); -int wifi_station_wps_start(void); -int wps_sm_rx_eapol_internal(u8 *src_addr, u8 *buf, u32 len); -void wifi_wps_start_internal(void); -int wifi_wps_enable_internal(const esp_wps_config_t *config); -int wifi_wps_disable_internal(void); -void wifi_station_wps_timeout_internal(void); -void wifi_station_wps_msg_timeout_internal(void); -void wifi_station_wps_success_internal(void); -void wifi_wps_scan_internal(void); -void wifi_station_wps_eapol_start_handle_internal(void); -void wps_add_discard_ap(u8 *bssid); - -void wifi_station_wps_msg_timeout(void *data, void *user_ctx); +static void wifi_wps_scan(void *data, void *user_ctx); +static int wifi_station_wps_start(void *data, void *user_ctx); +static int wifi_wps_enable_internal(void *ctx, void *data); +static int wifi_wps_disable_internal(void *ctx, void *data); +static void wifi_station_wps_msg_timeout(void *data, void *user_ctx); void wifi_station_wps_eapol_start_handle(void *data, void *user_ctx); -void wifi_station_wps_success(void *data, void *user_ctx); -void wifi_station_wps_timeout(void *data, void *user_ctx); -int wps_delete_timer(void); +static void wifi_station_wps_success(void *data, void *user_ctx); +static void wifi_station_wps_timeout(void *data, void *user_ctx); +static int wps_delete_timer(void); +static int wps_finish(void); struct wps_sm *gWpsSm = NULL; +static wifi_event_sta_wps_er_success_t s_wps_success_evt; static wps_factory_information_t *s_factory_info = NULL; -static void wps_rxq_init(void) -{ - DATA_MUTEX_TAKE(); - STAILQ_INIT(&s_wps_rxq); - DATA_MUTEX_GIVE(); -} - -static void wps_rxq_enqueue(struct wps_rx_param *param) -{ - DATA_MUTEX_TAKE(); - STAILQ_INSERT_TAIL(&s_wps_rxq, param, bqentry); - DATA_MUTEX_GIVE(); -} - -static struct wps_rx_param * wps_rxq_dequeue(void) -{ - struct wps_rx_param *param = NULL; - DATA_MUTEX_TAKE(); - if ((param = STAILQ_FIRST(&s_wps_rxq)) != NULL) { - STAILQ_REMOVE_HEAD(&s_wps_rxq, bqentry); - STAILQ_NEXT(param, bqentry) = NULL; - } - DATA_MUTEX_GIVE(); - return param; -} - -static void wps_rxq_deinit(void) -{ - struct wps_rx_param *param = NULL; - DATA_MUTEX_TAKE(); - while ((param = STAILQ_FIRST(&s_wps_rxq)) != NULL) { - STAILQ_REMOVE_HEAD(&s_wps_rxq, bqentry); - STAILQ_NEXT(param, bqentry) = NULL; - os_free(param->buf); - os_free(param); - } - DATA_MUTEX_GIVE(); -} - -#ifdef USE_WPS_TASK -void wps_task(void *pvParameters) -{ - ETSEvent e; - wps_ioctl_param_t *param; - bool del_task = false; - - os_semphr_give(s_wps_task_create_sem); - - wpa_printf(MSG_DEBUG, "wps_Task enter"); - for (;;) { - if (TRUE == os_queue_recv(s_wps_queue, &e, OS_BLOCK)) { - - if ((e.sig >= SIG_WPS_ENABLE) && (e.sig < SIG_WPS_NUM)) { - DATA_MUTEX_TAKE(); - if (s_wps_sig_cnt[e.sig]) { - s_wps_sig_cnt[e.sig]--; - } else { - wpa_printf(MSG_ERROR, "wpsT: invalid sig cnt, sig=%" PRId32 " cnt=%d", e.sig, s_wps_sig_cnt[e.sig]); - } - DATA_MUTEX_GIVE(); - } - - wpa_printf(MSG_DEBUG, "wpsT: rx sig=%" PRId32 "", e.sig); - - switch (e.sig) { - case SIG_WPS_ENABLE: - case SIG_WPS_DISABLE: - case SIG_WPS_START: - param = (wps_ioctl_param_t *)e.par; - if (!param) { - wpa_printf(MSG_ERROR, "wpsT: invalid param sig=%" PRId32 "", e.sig); - os_semphr_give(s_wps_api_sem); - break; - } - - if (e.sig == SIG_WPS_ENABLE) { - param->ret = wifi_wps_enable_internal((esp_wps_config_t *)(param->arg)); - } else if (e.sig == SIG_WPS_DISABLE) { - DATA_MUTEX_TAKE(); - param->ret = wifi_wps_disable_internal(); - del_task = true; - s_wps_task_hdl = NULL; - DATA_MUTEX_GIVE(); - } else { - param->ret = wifi_station_wps_start(); - } - - os_semphr_give(s_wps_api_sem); - break; - - case SIG_WPS_RX: { - struct wps_rx_param *param = NULL; - while ((param = wps_rxq_dequeue()) != NULL) { - wps_sm_rx_eapol_internal(param->sa, param->buf, param->len); - os_free(param->buf); - os_free(param); - } - break; - } - - case SIG_WPS_TIMER_TIMEOUT: - wifi_station_wps_timeout_internal(); - break; - - case SIG_WPS_TIMER_MSG_TIMEOUT: - wifi_station_wps_msg_timeout_internal(); - break; - - case SIG_WPS_TIMER_SUCCESS_CB: - wifi_station_wps_success_internal(); - break; - - case SIG_WPS_TIMER_SCAN: - wifi_wps_scan_internal(); - break; - - case SIG_WPS_TIMER_EAPOL_START: - wifi_station_wps_eapol_start_handle_internal(); - break; - - default: - wpa_printf(MSG_ERROR, "wpsT: invalid sig=%" PRId32 "", e.sig); - break; - } - - if (del_task) { - wpa_printf(MSG_DEBUG, "wpsT: delete task"); - break; - } - } - } - os_task_delete(NULL); -} - -/* wps_post() is thread-safe - * - */ -int wps_post(uint32_t sig, uint32_t par) -{ - wpa_printf(MSG_DEBUG, "wps post: sig=%" PRId32 " cnt=%d", sig, s_wps_sig_cnt[sig]); - ETSEvent evt; - - if (!s_wps_task_hdl) { - wpa_printf(MSG_DEBUG, "wps post: sig=%" PRId32 " failed as wps task has been deinited", sig); - return ESP_FAIL; - } - DATA_MUTEX_TAKE(); - if (s_wps_sig_cnt[sig]) { - wpa_printf(MSG_DEBUG, "wps post: sig=%" PRId32 " processing", sig); - DATA_MUTEX_GIVE(); - return ESP_OK; - } - - s_wps_sig_cnt[sig]++; - evt.sig = sig; - evt.par = par; - DATA_MUTEX_GIVE(); - - if (os_queue_send(s_wps_queue, &evt, os_task_ms_to_tick(10)) != TRUE) { - wpa_printf(MSG_ERROR, "WPS: Q S E"); - DATA_MUTEX_TAKE(); - s_wps_sig_cnt[sig]--; - DATA_MUTEX_GIVE(); - return ESP_FAIL; - } - return ESP_OK; -} -#endif - /* * wps_sm_ether_send - Send Ethernet frame * @wpa_s: Pointer to wpa_supplicant data @@ -261,34 +99,37 @@ static inline int wps_sm_ether_send(struct wps_sm *sm, u16 proto, int ret = esp_wifi_get_assoc_bssid_internal(bssid); if (ret != 0) { - wpa_printf(MSG_ERROR, "bssid is empty!"); + wpa_printf(MSG_ERROR, "WPS: BSSID is empty, cannot send EAPOL frame"); return -1; } return wpa_ether_send(sm, bssid, proto, data, data_len); } -u8 *wps_sm_alloc_eapol(struct wps_sm *sm, u8 type, - const void *data, u16 data_len, - size_t *msg_len, void **data_pos) +static inline u8 *wps_sm_alloc_eapol(struct wps_sm *sm, u8 type, + const void *data, u16 data_len, + size_t *msg_len, void **data_pos) { return wpa_alloc_eapol(sm, type, data, data_len, msg_len, data_pos); } -void wps_sm_free_eapol(u8 *buffer) +static inline void wps_sm_free_eapol(u8 *buffer) { return wpa_free_eapol(buffer); } -static void -wps_build_ic_appie_wps_pr(void) +static void wps_build_ic_appie_wps_pr(void) { + struct wps_sm *sm = wps_sm_get(); struct wpabuf *extra_ie = NULL; struct wpabuf *wps_ie; - struct wps_sm *sm = gWpsSm; u16 pw_id; - wpa_printf(MSG_DEBUG, "wps build: wps pr"); + if (!sm) { + return; + } + + wpa_printf(MSG_DEBUG, "WPS: Building Probe Request IE"); if (wps_get_type() == WPS_TYPE_PBC) { pw_id = DEV_PW_PUSHBUTTON; @@ -314,12 +155,11 @@ wps_build_ic_appie_wps_pr(void) wpabuf_free(extra_ie); } -static void -wps_build_ic_appie_wps_ar(void) +static void wps_build_ic_appie_wps_ar(void) { struct wpabuf *buf = wps_build_assoc_req_ie(WPS_REQ_ENROLLEE); - wpa_printf(MSG_DEBUG, "wps build: wps ar"); + wpa_printf(MSG_DEBUG, "WPS: Building Association Request IE"); if (buf) { esp_wifi_set_appie_internal(WIFI_APPIE_WPS_AR, (uint8_t *)wpabuf_head(buf), buf->used, 0); @@ -327,7 +167,34 @@ wps_build_ic_appie_wps_ar(void) } } -static bool ap_supports_sae(struct wps_scan_ie *scan) +static int wps_send_eapol_frame(u8 eapol_type, const void *payload, size_t payload_len) +{ + struct wps_sm *sm = gWpsSm; + u8 *buf; + int len; + int ret; + + if (!sm) { + return ESP_FAIL; + } + + buf = wps_sm_alloc_eapol(sm, eapol_type, payload, payload_len, (size_t *)&len, NULL); + if (!buf) { + wpa_printf(MSG_ERROR, "WPS: EAPOL buffer allocation failed"); + return ESP_ERR_NO_MEM; + } + + ret = wps_sm_ether_send(sm, ETH_P_EAPOL, buf, len); + wps_sm_free_eapol(buf); + + if (ret) { + wpa_printf(MSG_ERROR, "WPS: EAPOL send failed (ret=%d)", ret); + return ESP_FAIL; + } + return ESP_OK; +} + +static bool is_ap_supports_sae(struct wps_scan_ie *scan) { struct wpa_ie_data rsn_info; @@ -344,8 +211,7 @@ static bool ap_supports_sae(struct wps_scan_ie *scan) return false; } -static bool -is_wps_pbc_overlap(struct wps_sm *sm, const u8 *sel_uuid) +static bool is_wps_pbc_overlap(struct wps_sm *sm, const u8 *sel_uuid) { if (!sel_uuid) { wpa_printf(MSG_DEBUG, "WPS: null uuid field"); @@ -353,7 +219,7 @@ is_wps_pbc_overlap(struct wps_sm *sm, const u8 *sel_uuid) } if (os_memcmp(sel_uuid, sm->uuid_r, WPS_UUID_LEN) != 0) { - wpa_printf(MSG_DEBUG, "uuid is not same"); + wpa_printf(MSG_DEBUG, "WPS: Scanned BSS UUID does not match"); wpa_hexdump(MSG_DEBUG, "WPS: UUID of scanned BSS is", sel_uuid, WPS_UUID_LEN); wpa_hexdump(MSG_DEBUG, "WPS: UUID of sm BSS is", @@ -364,12 +230,15 @@ is_wps_pbc_overlap(struct wps_sm *sm, const u8 *sel_uuid) return false; } -static bool -wps_parse_scan_result(struct wps_scan_ie *scan) +static bool wps_parse_scan_result(struct wps_scan_ie *scan) { - struct wps_sm *sm = gWpsSm; + struct wps_sm *sm = wps_sm_get(); wifi_mode_t op_mode = 0; + if (!sm) { + return false; + } + if (sm->wps_pbc_overlap) { return false; } @@ -395,40 +264,22 @@ wps_parse_scan_result(struct wps_scan_ie *scan) } if (!scan->rsn && !scan->wpa && (scan->capinfo & WLAN_CAPABILITY_PRIVACY)) { - wpa_printf(MSG_DEBUG, "WEP not suppported in WPS"); - return false; - } - - if (sm->ignore_sel_reg && !is_zero_ether_addr(sm->bssid)) { - /* We have selected candidate for this scan */ + wpa_printf(MSG_DEBUG, "WPS: WEP not supported, skipping AP"); return false; } if (scan->wps) { bool ap_found = false; struct wpabuf *buf = wpabuf_alloc_copy(scan->wps + 6, scan->wps[1] - 4); - int count; const u8 *scan_uuid; if ((wps_get_type() == WPS_TYPE_PBC && wps_is_selected_pbc_registrar(buf)) || (wps_get_type() == WPS_TYPE_PIN && wps_is_addr_authorized(buf, sm->ownaddr, 1))) { /* Found one AP with selected registrar true */ - sm->ignore_sel_reg = false; - sm->discard_ap_cnt = 0; ap_found = true; } - if (wps_get_type() == WPS_TYPE_PIN && sm->ignore_sel_reg) { - /* AP is in discard list? */ - for (count = 0; count < WPS_MAX_DIS_AP_NUM; count++) { - if (os_memcmp(sm->dis_ap_list[count].bssid, scan->bssid, ETH_ALEN) == 0) { - wpa_printf(MSG_INFO, "discard ap bssid "MACSTR, MAC2STR(scan->bssid)); - wpabuf_free(buf); - return false; - } - } - } - if (ap_found || sm->ignore_sel_reg) { + if (ap_found) { if (scan->ssid[1] > SSID_MAX_LEN) { wpabuf_free(buf); return false; @@ -438,15 +289,15 @@ wps_parse_scan_result(struct wps_scan_ie *scan) os_memcpy(sm->creds[0].ssid, (char *)&scan->ssid[2], (int)scan->ssid[1]); sm->creds[0].ssid_len = scan->ssid[1]; if (scan->bssid && memcmp(sm->bssid, scan->bssid, ETH_ALEN) != 0) { - wpa_printf(MSG_INFO, "sm BSSid: "MACSTR " scan BSSID " MACSTR, + wpa_printf(MSG_DEBUG, "WPS: BSSID changed from " MACSTR " to " MACSTR, MAC2STR(sm->bssid), MAC2STR(scan->bssid)); sm->discover_ssid_cnt++; - wpa_printf(MSG_INFO, "discoverd cnt is %d and chan is %d ", sm->discover_ssid_cnt, scan->chan); + wpa_printf(MSG_DEBUG, "WPS: AP discovery count: %d, channel: %d ", sm->discover_ssid_cnt, scan->chan); os_memcpy(sm->bssid, scan->bssid, ETH_ALEN); scan_uuid = wps_get_uuid_e(buf); if (sm->discover_ssid_cnt > 1 && wps_get_type() == WPS_TYPE_PBC && is_wps_pbc_overlap(sm, scan_uuid) == true) { - wpa_printf(MSG_INFO, "pbc_overlap flag is true"); + wpa_printf(MSG_WARNING, "WPS: PBC overlap detected"); sm->wps_pbc_overlap = true; wpabuf_free(buf); return false; @@ -455,8 +306,8 @@ wps_parse_scan_result(struct wps_scan_ie *scan) os_memcpy(sm->uuid_r, scan_uuid, WPS_UUID_LEN); } - if (ap_supports_sae(scan)) { - wpa_printf(MSG_INFO, "AP supports SAE, get password in passphrase"); + if (is_ap_supports_sae(scan)) { + wpa_printf(MSG_INFO, "WPS: AP supports SAE"); sm->dev->config_methods |= WPS_CONFIG_DISPLAY | WPS_CONFIG_VIRT_DISPLAY; sm->wps->wps->config_methods |= WPS_CONFIG_DISPLAY | WPS_CONFIG_VIRT_DISPLAY; /* Reset assoc req, probe reset not needed */ @@ -464,7 +315,7 @@ wps_parse_scan_result(struct wps_scan_ie *scan) } } wpabuf_free(buf); - wpa_printf(MSG_DEBUG, "wps discover [%s] ", (char *)sm->creds[0].ssid); + wpa_printf(MSG_INFO, "WPS AP discovered: %s", (char *)sm->creds[0].ssid); sm->channel = scan->chan; return true; @@ -475,54 +326,39 @@ wps_parse_scan_result(struct wps_scan_ie *scan) return false; } -int wps_send_eap_identity_rsp(u8 id) +static int wps_send_eap_identity_rsp(u8 id) { - struct wps_sm *sm = gWpsSm; + struct wps_sm *sm = wps_sm_get(); struct wpabuf *eap_buf = NULL; - u8 *buf = NULL; - int len; int ret = ESP_OK; - wpa_printf(MSG_DEBUG, "wps send eapol id rsp"); + if (!sm) { + return ESP_FAIL; + } + + wpa_printf(MSG_DEBUG, "WPS: Sending EAP-Identity Response"); eap_buf = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, sm->identity_len, EAP_CODE_RESPONSE, id); if (!eap_buf) { - wpa_printf(MSG_ERROR, "eap buf allocation failed"); - ret = ESP_FAIL; - goto _err; + wpa_printf(MSG_ERROR, "WPS: EAP buffer allocation failed"); + return ESP_ERR_NO_MEM; } wpabuf_put_data(eap_buf, sm->identity, sm->identity_len); - buf = wps_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAP_PACKET, wpabuf_head_u8(eap_buf), wpabuf_len(eap_buf), (size_t *)&len, NULL); - if (!buf) { - wpa_printf(MSG_ERROR, "buf allocation failed"); - ret = ESP_ERR_NO_MEM; - goto _err; - } + ret = wps_send_eapol_frame(IEEE802_1X_TYPE_EAP_PACKET, wpabuf_head(eap_buf), wpabuf_len(eap_buf)); - ret = wps_sm_ether_send(sm, ETH_P_EAPOL, buf, len); - if (ret) { - wpa_printf(MSG_ERROR, "wps sm ether send failed ret=%d", ret); - ret = ESP_FAIL; - goto _err; - } - -_err: - wps_sm_free_eapol(buf); wpabuf_free(eap_buf); return ret; } -int wps_send_frag_ack(u8 id) +static int wps_send_frag_ack(u8 id) { - struct wps_sm *sm = gWpsSm; + struct wps_sm *sm = wps_sm_get(); struct wpabuf *eap_buf = NULL; - u8 *buf; - int len; - int ret = 0; + int ret = ESP_OK; - wpa_printf(MSG_DEBUG, "send frag ack id:%d", id); + wpa_printf(MSG_DEBUG, "WPS: Sending EAP-WSC Frag-ACK (id:%d)", id); if (!sm) { return ESP_FAIL; @@ -530,47 +366,31 @@ int wps_send_frag_ack(u8 id) eap_buf = eap_wsc_build_frag_ack(id, EAP_CODE_RESPONSE); if (!eap_buf) { - ret = ESP_ERR_NO_MEM; - goto _err; + return ESP_ERR_NO_MEM; } - buf = wps_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAP_PACKET, wpabuf_head_u8(eap_buf), wpabuf_len(eap_buf), (size_t *)&len, NULL); - if (!buf) { - ret = ESP_ERR_NO_MEM; - goto _err; - } + ret = wps_send_eapol_frame(IEEE802_1X_TYPE_EAP_PACKET, wpabuf_head(eap_buf), wpabuf_len(eap_buf)); - ret = wps_sm_ether_send(sm, ETH_P_EAPOL, buf, len); - wps_sm_free_eapol(buf); - if (ret) { - ret = ESP_ERR_NO_MEM; - goto _err; - } - -_err: wpabuf_free(eap_buf); + return ret; } -int wps_enrollee_process_msg_frag(struct wpabuf **buf, int tot_len, u8 *frag_data, int frag_len, u8 flag) +static int wps_enrollee_process_msg_frag(struct wpabuf **buf, int tot_len, u8 *frag_data, int frag_len, u8 flag) { - struct wps_sm *sm = gWpsSm; + struct wps_sm *sm = wps_sm_get(); u8 identifier; - if (!sm) { + if (!sm || !buf || !frag_data) { + wpa_printf(MSG_ERROR, "WPS: %s: Invalid arguments", __func__); return ESP_FAIL; } identifier = sm->current_identifier; - if (buf == NULL || frag_data == NULL) { - wpa_printf(MSG_ERROR, "fun:%s. line:%d, frag buf or frag data is null", __FUNCTION__, __LINE__); - return ESP_FAIL; - } - if (*buf == NULL) { if (0 == (flag & WPS_MSG_FLAG_LEN) || tot_len < frag_len) { - wpa_printf(MSG_ERROR, "fun:%s. line:%d, flag error:%02x", __FUNCTION__, __LINE__, flag); + wpa_printf(MSG_ERROR, "WPS: %s: Invalid fragment flag: 0x%02x", __FUNCTION__, flag); return ESP_FAIL; } @@ -584,7 +404,7 @@ int wps_enrollee_process_msg_frag(struct wpabuf **buf, int tot_len, u8 *frag_dat } if (flag & WPS_MSG_FLAG_LEN) { - wpa_printf(MSG_ERROR, "fun:%s. line:%d, flag error:%02x", __FUNCTION__, __LINE__, flag); + wpa_printf(MSG_ERROR, "WPS: %s: Invalid fragment flag: 0x%02x", __func__, flag); return ESP_FAIL; } @@ -597,9 +417,22 @@ int wps_enrollee_process_msg_frag(struct wpabuf **buf, int tot_len, u8 *frag_dat return ESP_OK; } -int wps_process_wps_mX_req(u8 *ubuf, int len, enum wps_process_res *res) +static void wifi_station_wps_post_m8_timeout(void *data, void *user_ctx) { - struct wps_sm *sm = gWpsSm; + struct wps_sm *sm = wps_sm_get(); + + if (sm && sm->post_m8_recv) { + wpa_printf(MSG_DEBUG, "WPS: M8 workaround timeout, success!"); + sm->wps->state = WPS_FINISHED; + /* Reset it here so that deauth won't call wps finish again */ + sm->post_m8_recv = false; + wps_finish(); + } +}; + +static int wps_process_wps_mX_req(u8 *ubuf, int len, enum wps_process_res *res) +{ + struct wps_sm *sm = wps_sm_get(); static struct wpabuf *wps_buf = NULL; struct eap_expand *expd; int tlen = 0; @@ -613,18 +446,17 @@ int wps_process_wps_mX_req(u8 *ubuf, int len, enum wps_process_res *res) } expd = (struct eap_expand *) ubuf; - wpa_printf(MSG_DEBUG, "wps process mX req: len %d, tlen %d", len, tlen); + wpa_printf(MSG_DEBUG, "WPS: Processing WSC message (len=%d, total_len=%d)", len, tlen); if (sm->state == WAIT_START) { if (expd->opcode != WSC_Start) { - wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d " - "in WAIT_START state", expd->opcode); + wpa_printf(MSG_WARNING, "WPS: Unexpected Op-Code %d in WAIT_START state", expd->opcode); return ESP_ERR_INVALID_STATE; } - wpa_printf(MSG_DEBUG, "EAP-WSC: Received start"); + wpa_printf(MSG_DEBUG, "WPS: Received EAP-WSC Start"); sm->state = WPA_MESG; } else if (expd->opcode == WSC_Start) { - wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d", + wpa_printf(MSG_WARNING, "WPS: Unexpected Op-Code %d", expd->opcode); return ESP_ERR_INVALID_STATE; } @@ -642,11 +474,11 @@ int wps_process_wps_mX_req(u8 *ubuf, int len, enum wps_process_res *res) } if (tlen > 50000) { - wpa_printf(MSG_ERROR, "EAP-WSC: Invalid Message Length"); + wpa_printf(MSG_ERROR, "WPS: Invalid EAP-WSC message length"); return ESP_FAIL; } if ((flag & WPS_MSG_FLAG_MORE) || wps_buf != NULL) {//frag msg - wpa_printf(MSG_DEBUG, "rx frag msg id:%d, flag:%d, frag_len: %d, tot_len: %d, be_tot_len:%d", sm->current_identifier, flag, frag_len, tlen, be_tot_len); + wpa_printf(MSG_DEBUG, "WPS: Received fragment (id=%d, flag=0x%x, frag_len=%d, total_len=%d)", sm->current_identifier, flag, frag_len, tlen); if (ESP_OK != wps_enrollee_process_msg_frag(&wps_buf, tlen, tbuf, frag_len, flag)) { if (wps_buf) { wpabuf_free(wps_buf); @@ -660,7 +492,7 @@ int wps_process_wps_mX_req(u8 *ubuf, int len, enum wps_process_res *res) } } else { //not frag msg if (wps_buf) {//if something wrong, frag msg buf is not freed, free first - wpa_printf(MSG_ERROR, "something is wrong, frag buf is not freed"); + wpa_printf(MSG_ERROR, "WPS: Fragment buffer not freed before receiving new message"); wpabuf_free(wps_buf); wps_buf = NULL; } @@ -675,6 +507,13 @@ int wps_process_wps_mX_req(u8 *ubuf, int len, enum wps_process_res *res) *res = wps_enrollee_process_msg(sm->wps, expd->opcode, wps_buf); + if (*res == WPS_CONTINUE && sm->wps->state == WPS_MSG_DONE) { + wpa_printf(MSG_DEBUG, "WPS: M8 processed, starting workaround timer"); + sm->post_m8_recv = true; + eloop_cancel_timeout(wifi_station_wps_post_m8_timeout, NULL, NULL); + eloop_register_timeout(WPS_POST_M8_WORKAROUND_SECS, 0, wifi_station_wps_post_m8_timeout, NULL, NULL); + } + if (*res == WPS_FAILURE) { sm->state = WPA_FAIL; } @@ -686,17 +525,15 @@ int wps_process_wps_mX_req(u8 *ubuf, int len, enum wps_process_res *res) return ESP_OK; } -int wps_send_wps_mX_rsp(u8 id) +static int wps_send_wps_mX_rsp(u8 id) { - struct wps_sm *sm = gWpsSm; + struct wps_sm *sm = wps_sm_get(); struct wpabuf *eap_buf = NULL; struct wpabuf *wps_buf = NULL; - u8 *buf; - int len; - int ret = 0; + int ret = ESP_OK; enum wsc_op_code opcode; - wpa_printf(MSG_DEBUG, "wps send wps mX rsp"); + wpa_printf(MSG_DEBUG, "WPS: Sending WSC Message"); if (!sm) { return ESP_FAIL; @@ -704,131 +541,131 @@ int wps_send_wps_mX_rsp(u8 id) wps_buf = wps_enrollee_get_msg(sm->wps, &opcode); if (!wps_buf) { - ret = ESP_FAIL; - goto _err; + return ESP_FAIL; } eap_buf = eap_msg_alloc(EAP_VENDOR_WFA, 0x00000001, wpabuf_len(wps_buf) + 2, EAP_CODE_RESPONSE, id); if (!eap_buf) { - ret = ESP_FAIL; - goto _err; + wpabuf_free(wps_buf); + return ESP_ERR_NO_MEM; } wpabuf_put_u8(eap_buf, opcode); wpabuf_put_u8(eap_buf, 0x00); /* flags */ - wpabuf_put_data(eap_buf, wpabuf_head_u8(wps_buf), wpabuf_len(wps_buf)); - + wpabuf_put_data(eap_buf, wpabuf_head(wps_buf), wpabuf_len(wps_buf)); wpabuf_free(wps_buf); - buf = wps_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAP_PACKET, wpabuf_head_u8(eap_buf), wpabuf_len(eap_buf), (size_t *)&len, NULL); - if (!buf) { - ret = ESP_FAIL; - goto _err; - } + ret = wps_send_eapol_frame(IEEE802_1X_TYPE_EAP_PACKET, wpabuf_head(eap_buf), wpabuf_len(eap_buf)); - ret = wps_sm_ether_send(sm, ETH_P_EAPOL, buf, len); - wps_sm_free_eapol(buf); - if (ret) { - ret = ESP_FAIL; - goto _err; - } - -_err: wpabuf_free(eap_buf); return ret; } -int wps_tx_start(void) +static int wps_tx_start(void) { - struct wps_sm *sm = gWpsSm; - u8 *buf; - int len; + wpa_printf(MSG_DEBUG, "WPS: Sending EAPOL-Start"); - if (!sm) { + if (wps_send_eapol_frame(IEEE802_1X_TYPE_EAPOL_START, (u8 *)"", 0) != ESP_OK) { return ESP_FAIL; } - wpa_printf(MSG_DEBUG, "WPS: Send EAPOL START."); - buf = wps_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_START, (u8 *)"", 0, (size_t *)&len, NULL); - if (!buf) { - return ESP_ERR_NO_MEM; - } - - wps_sm_ether_send(sm, ETH_P_EAPOL, buf, len); - wps_sm_free_eapol(buf); - - eloop_register_timeout(3, 0, wifi_station_wps_eapol_start_handle, NULL, NULL); + eloop_cancel_timeout(wifi_station_wps_eapol_start_handle, NULL, NULL); + eloop_register_timeout(EAPOL_START_HANDLE_TIMEOUT_SECS, 0, wifi_station_wps_eapol_start_handle, NULL, NULL); return ESP_OK; } -int wps_start_pending(void) +static int wps_start_pending(void) { - if (!gWpsSm) { + if (!wps_sm_get()) { return ESP_FAIL; } - wpa_printf(MSG_DEBUG, "wps start pending"); + wpa_printf(MSG_DEBUG, "WPS: Pending start, sending EAPOL-Start"); return wps_tx_start(); } -static void wps_stop_connection_timers(struct wps_sm *sm) +static int wps_send_event_and_disable(int32_t event_id, void* event_data, size_t data_len) { - esp_wifi_disarm_sta_connection_timer_internal(); - eloop_cancel_timeout(wifi_station_wps_msg_timeout, NULL, NULL); - eloop_cancel_timeout(wifi_station_wps_success, NULL, NULL); -} - -static int wps_sm_init(struct wps_sm *sm) -{ - if (!sm) { - return -1; + if (gWpsSm == NULL) { + return 0; } - sm->ignore_sel_reg = false; - sm->discard_ap_cnt = 0; - sm->scan_cnt = 0; - sm->discover_ssid_cnt = 0; - os_bzero(sm->bssid, ETH_ALEN); - os_bzero(sm->creds, sizeof(sm->creds)); - sm->ap_cred_cnt = 0; + +#ifdef CONFIG_WPS_RECONNECT_ON_FAIL + /* On failure, reconnect to the previous AP if one was saved */ + if (s_previous_wifi_config) { + wpa_printf(MSG_INFO, "WPS failed, reconnecting to previous AP: %s", (char *)s_previous_wifi_config->sta.ssid); + esp_wifi_set_config(WIFI_IF_STA, s_previous_wifi_config); + esp_wifi_connect(); + os_free(s_previous_wifi_config); + s_previous_wifi_config = NULL; + } +#endif + + esp_event_post(WIFI_EVENT, event_id, event_data, data_len, OS_BLOCK); + + wps_set_type(WPS_TYPE_DISABLE); + wifi_wps_disable_internal(NULL, NULL); + + API_MUTEX_TAKE(); + s_wps_enabled = false; + API_MUTEX_GIVE(); return 0; } -int wps_stop_process(wifi_event_sta_wps_fail_reason_t reason_code) +static int wps_handle_failure(wifi_event_sta_wps_fail_reason_t reason_code) { - struct wps_sm *sm = gWpsSm; + struct wps_sm *sm = wps_sm_get(); - if (!gWpsSm) { + if (!sm) { return ESP_FAIL; } - wps_set_status(WPS_STATUS_DISABLE); - wps_sm_init(sm); + wpa_printf(MSG_INFO, "WPS process stopping."); - sm->wps->state = SEND_M1; - wps_stop_connection_timers(sm); + /* Disconnect from AP before disabling WPS */ esp_wifi_disconnect(); - sm->state = WPA_FAIL; - wpa_printf(MSG_DEBUG, "Write wps_fail_information"); - - esp_event_post(WIFI_EVENT, WIFI_EVENT_STA_WPS_ER_FAILED, &reason_code, sizeof(reason_code), OS_BLOCK); + wps_send_event_and_disable(WIFI_EVENT_STA_WPS_ER_FAILED, &reason_code, sizeof(reason_code)); return ESP_OK; } -int wps_finish(void) +static void wifi_station_fill_event_info(struct wps_sm *sm, wifi_event_sta_wps_er_success_t *evt) { - struct wps_sm *sm = gWpsSm; + int i; + + os_memset(evt, 0, sizeof(*evt)); + if (sm && sm->ap_cred_cnt > 1) { + evt->ap_cred_cnt = sm->ap_cred_cnt < MAX_WPS_AP_CRED ? sm->ap_cred_cnt : MAX_WPS_AP_CRED; + for (i = 0; i < evt->ap_cred_cnt; i++) { + os_memcpy(evt->ap_cred[i].ssid, sm->creds[i].ssid, sm->creds[i].ssid_len); + os_memcpy(evt->ap_cred[i].passphrase, sm->creds[i].key, sm->creds[i].key_len); + } + } +} + +static int wps_finish(void) +{ + struct wps_sm *sm = wps_sm_get(); int ret = ESP_FAIL; - if (!gWpsSm) { + if (!sm) { return ESP_FAIL; } if (sm->wps->state == WPS_FINISHED) { - wpa_printf(MSG_DEBUG, "wps finished------>"); + bool connect = (sm->ap_cred_cnt == 1); + +#ifdef CONFIG_WPS_RECONNECT_ON_FAIL + if (s_previous_wifi_config) { + os_free(s_previous_wifi_config); + s_previous_wifi_config = NULL; + } +#endif + + wpa_printf(MSG_INFO, "WPS: Succeeded"); wps_set_status(WPS_STATUS_SUCCESS); /* WPS finished, dequeue all timers */ wps_delete_timer(); @@ -840,15 +677,13 @@ int wps_finish(void) if (sm->ap_cred_cnt == 1) { wifi_config_t *config = os_zalloc(sizeof(wifi_config_t)); - if (config == NULL) { + if (!config) { return ESP_FAIL; } esp_wifi_get_config(WIFI_IF_STA, config); - esp_wifi_disconnect(); os_memcpy(config->sta.ssid, sm->creds[0].ssid, sm->creds[0].ssid_len); os_memcpy(config->sta.password, sm->creds[0].key, sm->creds[0].key_len); - os_memcpy(config->sta.bssid, sm->bssid, ETH_ALEN); #ifndef CONFIG_WPS_STRICT /* Some APs support AES in WPA IE, enable connection with them */ if (sm->creds[0].auth_type == WPS_AUTH_WPAPSK && @@ -858,80 +693,77 @@ int wps_finish(void) #endif config->sta.bssid_set = 0; config->sta.sae_pwe_h2e = 0; + esp_wifi_disconnect(); esp_wifi_set_config(WIFI_IF_STA, config); - esp_wifi_connect(); - os_free(config); } + + /* fill event info */ + wifi_station_fill_event_info(sm, &s_wps_success_evt); + + /* Disable WPS when success */ + wps_set_type(WPS_TYPE_DISABLE); + wifi_wps_disable_internal(NULL, NULL); + + if (connect) { + esp_wifi_connect(); + } + + /* wait for 1 sec before sending WPS success event to give connection time */ + /* TODO: Remove disconnection event during WPS session to make it cleaner */ eloop_cancel_timeout(wifi_station_wps_success, NULL, NULL); - eloop_register_timeout(1, 0, wifi_station_wps_success, NULL, NULL); + eloop_register_timeout(WPS_SUCCESS_EVENT_TIMEOUT_SECS, 0, wifi_station_wps_success, NULL, NULL); ret = 0; } else { - wpa_printf(MSG_ERROR, "wps failed-----> ignore_sel_reg=%d", sm->ignore_sel_reg); - if (sm->ignore_sel_reg) { - sm->discover_ssid_cnt = 0; - esp_wifi_disconnect(); - os_bzero(sm->creds, sizeof(sm->creds)); - wps_add_discard_ap(sm->bssid); - } else { - ret = wps_stop_process(WPS_FAIL_REASON_NORMAL); - } + wpa_printf(MSG_ERROR, "WPS failed with state %d", sm->wps->state); + ret = wps_handle_failure(WPS_FAIL_REASON_NORMAL); } + API_MUTEX_TAKE(); + s_wps_enabled = false; + API_MUTEX_GIVE(); + return ret; } /* This will get executed in the wifi task's context */ static void wps_sm_notify_deauth(void) { - if (gWpsSm && gWpsSm->wps->state != WPS_FINISHED && - !gWpsSm->intermediate_disconnect) { - wps_stop_process(WPS_FAIL_REASON_RECV_DEAUTH); - } -} + struct wps_sm *sm = wps_sm_get(); -/* Add current ap to discard ap list */ -void wps_add_discard_ap(u8 *bssid) -{ - struct wps_sm *sm = gWpsSm; - u8 cnt = sm->discard_ap_cnt; - - if (!gWpsSm || !bssid) { + if (sm && sm->post_m8_recv) { + wpa_printf(MSG_DEBUG, "WPS: deauth after M8, considering success"); + eloop_cancel_timeout(wifi_station_wps_post_m8_timeout, NULL, NULL); + sm->wps->state = WPS_FINISHED; + wps_finish(); return; } - - if (sm->discard_ap_cnt < WPS_MAX_DIS_AP_NUM) { - sm->discard_ap_cnt++; - } else { - for (cnt = 0; cnt < WPS_MAX_DIS_AP_NUM - 2; cnt++) { - os_memcpy(sm->dis_ap_list[cnt].bssid, sm->dis_ap_list[cnt + 1].bssid, 6); - } - sm->discard_ap_cnt = WPS_MAX_DIS_AP_NUM; + if (sm && sm->wps && sm->wps->state != WPS_FINISHED) { + wpa_printf(MSG_ERROR, "WPS: Deauthenticated during handshake"); + wps_handle_failure(WPS_FAIL_REASON_RECV_DEAUTH); } - os_memcpy(sm->dis_ap_list[cnt].bssid, bssid, ETH_ALEN); - wpa_printf(MSG_INFO, "Added BSSID:"MACSTR" to discard list cnt=%d" , MAC2STR(bssid), sm->discard_ap_cnt); } int wps_start_msg_timer(void) { - struct wps_sm *sm = gWpsSm; + struct wps_sm *sm = wps_sm_get(); uint32_t msg_timeout; int ret = ESP_FAIL; - if (!gWpsSm) { + if (!sm) { return ESP_FAIL; } if (sm->wps->state == WPS_FINISHED) { - msg_timeout = 5; - wpa_printf(MSG_DEBUG, "start msg timer WPS_FINISHED %" PRId32 " ms", msg_timeout); + msg_timeout = WPS_MSG_TIMEOUT_FINISH_SECS; + wpa_printf(MSG_DEBUG, "WPS: Starting M-Done timer (%u s)", msg_timeout); eloop_cancel_timeout(wifi_station_wps_msg_timeout, NULL, NULL); eloop_register_timeout(msg_timeout, 0, wifi_station_wps_msg_timeout, NULL, NULL); ret = 0; } else if (sm->wps->state == RECV_M2) { - msg_timeout = 20; - wpa_printf(MSG_DEBUG, "start msg timer RECV_M2 %" PRId32 " s", msg_timeout); + msg_timeout = WPS_MSG_TIMEOUT_M2_SECS; + wpa_printf(MSG_DEBUG, "WPS: Starting M2 timer (%u s)", msg_timeout); eloop_cancel_timeout(wifi_station_wps_msg_timeout, NULL, NULL); eloop_register_timeout(msg_timeout, 0, wifi_station_wps_msg_timeout, NULL, NULL); ret = 0; @@ -956,40 +788,9 @@ int wps_start_msg_timer(void) * successful key handshake. * buf begin from version, so remove mac header ,snap header and ether_type */ -int wps_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len) +static int wps_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len) { - if (!gWpsSm) { - return ESP_FAIL; - } - -#ifdef USE_WPS_TASK - { - struct wps_rx_param *param = os_zalloc(sizeof(struct wps_rx_param)); /* free in task */ - - if (!param) { - return ESP_ERR_NO_MEM; - } - - param->buf = os_zalloc(len); /* free in task */ - if (!param->buf) { - os_free(param); - return ESP_ERR_NO_MEM; - } - os_memcpy(param->buf, buf, len); - param->len = len; - os_memcpy(param->sa, src_addr, ETH_ALEN); - - wps_rxq_enqueue(param); - return wps_post(SIG_WPS_RX, 0); - } -#else - return wps_sm_rx_eapol_internal(src_addr, buf, len); -#endif -} - -int wps_sm_rx_eapol_internal(u8 *src_addr, u8 *buf, u32 len) -{ - struct wps_sm *sm = gWpsSm; + struct wps_sm *sm = wps_sm_get(); u32 plen, data_len, eap_len; struct ieee802_1x_hdr *hdr; struct eap_hdr *ehdr; @@ -999,56 +800,49 @@ int wps_sm_rx_eapol_internal(u8 *src_addr, u8 *buf, u32 len) int ret = ESP_FAIL; enum wps_process_res res = WPS_DONE; - if (!gWpsSm) { + if (!sm) { return ESP_FAIL; } if (len < sizeof(*hdr) + sizeof(*ehdr)) { - wpa_printf(MSG_DEBUG, "WPA: EAPOL frame too short to be a WPA " - "EAPOL-Key (len %lu, expecting at least %lu)", - (unsigned long) len, - (unsigned long) sizeof(*hdr) + sizeof(*ehdr)); + wpa_printf(MSG_DEBUG, "WPS: EAPOL frame too short (len=%lu)", + (unsigned long) len); return ESP_OK; } tmp = buf; hdr = (struct ieee802_1x_hdr *) tmp; - ehdr = (struct eap_hdr *) (hdr + 1); + ehdr = (struct eap_hdr *)(hdr + 1); plen = be_to_host16(hdr->length); data_len = plen + sizeof(*hdr); eap_len = be_to_host16(ehdr->length); - wpa_printf(MSG_DEBUG, "IEEE 802.1X RX: version=%d type=%d length=%" PRId32 "", - hdr->version, hdr->type, plen); + wpa_printf(MSG_DEBUG, "WPS: RX IEEE 802.1X: version=%d type=%d length=%u", hdr->version, hdr->type, plen); if (hdr->version < EAPOL_VERSION) { /* TODO: backwards compatibility */ } if (hdr->type != IEEE802_1X_TYPE_EAP_PACKET) { - wpa_printf(MSG_DEBUG, "WPS: EAP frame (type %u) discarded, " - "not a EAP PACKET frame", hdr->type); + wpa_printf(MSG_DEBUG, "WPS: Discarding non-EAP-PACKET frame (type %u)", hdr->type); ret = 0; goto out; } if (plen > len - sizeof(*hdr) || plen < sizeof(*ehdr)) { - wpa_printf(MSG_DEBUG, "WPA: EAPOL frame payload size %lu " - "invalid (frame size %lu)", + wpa_printf(MSG_DEBUG, "WPS: Invalid EAPOL payload size %lu (frame size %lu)", (unsigned long) plen, (unsigned long) len); ret = 0; goto out; } - wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL-EAP PACKET", tmp, len); + wpa_hexdump(MSG_MSGDUMP, "WPS: RX EAPOL-EAP Packet", tmp, len); if (data_len < len) { - wpa_printf(MSG_DEBUG, "WPA: ignoring %lu bytes after the IEEE " - "802.1X data", (unsigned long) len - data_len); + wpa_printf(MSG_DEBUG, "WPS: Ignoring %lu extra bytes in EAPOL frame", (unsigned long) len - data_len); } if (eap_len != plen) { - wpa_printf(MSG_DEBUG, "WPA: EAPOL length %lu " - "invalid (eapol length %lu)", + wpa_printf(MSG_DEBUG, "WPS: Invalid EAP length %lu in EAPOL frame (total payload %lu)", (unsigned long) eap_len, (unsigned long) plen); ret = 0; goto out; @@ -1057,36 +851,36 @@ int wps_sm_rx_eapol_internal(u8 *src_addr, u8 *buf, u32 len) eap_code = ehdr->code; switch (eap_code) { case EAP_CODE_SUCCESS: - wpa_printf(MSG_DEBUG, "error: receive eapol success frame!"); + wpa_printf(MSG_WARNING, "WPS: Unexpected EAP-Success frame received"); ret = 0; break; case EAP_CODE_FAILURE: - wpa_printf(MSG_DEBUG, "receive eap code failure!"); + wpa_printf(MSG_INFO, "WPS: Received EAP-Failure frame."); ret = wps_finish(); break; case EAP_CODE_RESPONSE: - wpa_printf(MSG_DEBUG, "error: receive eapol response frame!"); + wpa_printf(MSG_WARNING, "WPS: Unexpected EAP-Response frame received"); ret = 0; break; case EAP_CODE_REQUEST: eap_type = ((u8 *)ehdr)[sizeof(*ehdr)]; switch (eap_type) { case EAP_TYPE_IDENTITY: - wpa_printf(MSG_DEBUG, "=========identity==========="); + wpa_printf(MSG_DEBUG, "WPS: Received EAP-Request-Identity"); sm->current_identifier = ehdr->identifier; eloop_cancel_timeout(wifi_station_wps_eapol_start_handle, NULL, NULL); - wpa_printf(MSG_DEBUG, "WPS: Build EAP Identity."); + wpa_printf(MSG_DEBUG, "WPS: Building EAP-Identity Response."); ret = wps_send_eap_identity_rsp(ehdr->identifier); - eloop_register_timeout(3, 0, wifi_station_wps_eapol_start_handle, NULL, NULL); + eloop_register_timeout(EAPOL_START_HANDLE_TIMEOUT_SECS, 0, wifi_station_wps_eapol_start_handle, NULL, NULL); break; case EAP_TYPE_EXPANDED: - wpa_printf(MSG_DEBUG, "=========expanded plen[%" PRId32 "], %d===========", plen, sizeof(*ehdr)); + wpa_printf(MSG_DEBUG, "WPS: Received EAP-WSC message (len=%u)", plen); sm->current_identifier = ehdr->identifier; tmp = (u8 *)(ehdr + 1) + 1; ret = wps_process_wps_mX_req(tmp, plen - sizeof(*ehdr) - 1, &res); if (res == WPS_FRAGMENT) { - wpa_printf(MSG_DEBUG, "wps frag, silently exit", res); + wpa_printf(MSG_DEBUG, "WPS fragment received, waiting for more."); ret = ESP_OK; break; } @@ -1094,7 +888,7 @@ int wps_sm_rx_eapol_internal(u8 *src_addr, u8 *buf, u32 len) ret = wps_send_wps_mX_rsp(ehdr->identifier); if (ret == ESP_OK) { - wpa_printf(MSG_DEBUG, "sm->wps->state = %d", sm->wps->state); + wpa_printf(MSG_DEBUG, "WPS: State updated to %d", sm->wps->state); wps_start_msg_timer(); } } else if (ret == ESP_ERR_INVALID_STATE) { @@ -1111,29 +905,22 @@ int wps_sm_rx_eapol_internal(u8 *src_addr, u8 *buf, u32 len) break; } out: - if (ret != 0 && sm->ignore_sel_reg) { - wifi_wps_scan(NULL, NULL); - } else if ((ret != 0 || res == WPS_FAILURE)) { - wifi_event_sta_wps_fail_reason_t reason_code = WPS_FAIL_REASON_NORMAL; - wpa_printf(MSG_DEBUG, "wpa rx eapol internal: fail ret=%d", ret); - wps_set_status(WPS_STATUS_DISABLE); - esp_wifi_disarm_sta_connection_timer_internal(); - eloop_cancel_timeout(wifi_station_wps_timeout, NULL, NULL); + if ((ret != 0 || res == WPS_FAILURE)) { + wpa_printf(MSG_ERROR, "WPS: EAPOL processing failed (ret=%d)", ret); + wps_handle_failure(WPS_FAIL_REASON_NORMAL); - esp_event_post(WIFI_EVENT, WIFI_EVENT_STA_WPS_ER_FAILED, &reason_code, sizeof(reason_code), OS_BLOCK); - - return ret; + return ESP_FAIL; } return ret; } -int wps_set_default_factory(void) +static int wps_set_default_factory(void) { if (!s_factory_info) { s_factory_info = os_zalloc(sizeof(wps_factory_information_t)); if (!s_factory_info) { - wpa_printf(MSG_ERROR, "wps factory info malloc failed"); + wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for factory info"); return ESP_ERR_NO_MEM; } } @@ -1171,17 +958,16 @@ int wps_set_factory_info(const esp_wps_config_t *config) os_memcpy(s_factory_info->device_name, config->factory_info.device_name, WPS_MAX_DEVICE_NAME_LEN - 1); } - wpa_printf(MSG_INFO, "manufacturer: %s, model number: %s, model name: %s, device name: %s", s_factory_info->manufacturer, + wpa_printf(MSG_INFO, "WPS: Manufacturer: %s, Model: %s, Model-Num: %s, Device: %s", s_factory_info->manufacturer, s_factory_info->model_number, s_factory_info->model_name, s_factory_info->device_name); return ESP_OK; } - int wps_dev_init(void) { int ret = 0; - struct wps_sm *sm = gWpsSm; + struct wps_sm *sm = wps_sm_get(); struct wps_device_data *dev = NULL; if (!sm) { @@ -1247,8 +1033,8 @@ int wps_dev_init(void) goto _out; } os_snprintf(dev->serial_number, 16, "%02x%02x%02x%02x%02x%02x", - sm->ownaddr[0], sm->ownaddr[1], sm->ownaddr[2], - sm->ownaddr[3], sm->ownaddr[4], sm->ownaddr[5]); + sm->ownaddr[0], sm->ownaddr[1], sm->ownaddr[2], + sm->ownaddr[3], sm->ownaddr[4], sm->ownaddr[5]); uuid_gen_mac_addr(sm->ownaddr, sm->uuid); os_memcpy(dev->mac_addr, sm->ownaddr, ETH_ALEN); @@ -1260,11 +1046,8 @@ _out: return ret; } - int wps_dev_deinit(struct wps_device_data *dev) { - int ret = 0; - if (!dev) { return ESP_FAIL; } @@ -1275,137 +1058,74 @@ int wps_dev_deinit(struct wps_device_data *dev) s_factory_info = NULL; } - return ret; + return ESP_OK; } -void -wifi_station_wps_timeout_internal(void) +static void wifi_station_wps_timeout(void *data, void *user_ctx) { - struct wps_sm *sm = gWpsSm; - + struct wps_sm *sm = wps_sm_get(); if (!sm) { return; } + wpa_printf(MSG_ERROR, "WPS overall timeout!"); - esp_wifi_disarm_sta_connection_timer_internal(); - - wps_set_status(WPS_STATUS_DISABLE); - - esp_event_post(WIFI_EVENT, WIFI_EVENT_STA_WPS_ER_TIMEOUT, 0, 0, OS_BLOCK); + wps_send_event_and_disable(WIFI_EVENT_STA_WPS_ER_TIMEOUT, 0, 0); } -void wifi_station_wps_timeout(void *data, void *user_ctx) +static void wifi_station_wps_msg_timeout(void *data, void *user_ctx) { -#ifdef USE_WPS_TASK - wps_post(SIG_WPS_TIMER_TIMEOUT, 0); - return; -#else - wifi_station_wps_timeout_internal(); -#endif -} - -void -wifi_station_wps_msg_timeout_internal(void) -{ - struct wps_sm *sm = gWpsSm; + struct wps_sm *sm = wps_sm_get(); if (!sm) { return; } if (sm->wps->state == WPS_FINISHED) { - wpa_printf(MSG_DEBUG, "wps msg timeout WPS_FINISHED"); + wpa_printf(MSG_DEBUG, "WPS: M-Done timer expired, finishing."); wps_finish(); return; } else if (sm->wps->state == RECV_M2) { - wpa_printf(MSG_DEBUG, "wps msg timeout RECV_M2"); - if (!sm->ignore_sel_reg) { - wps_stop_process(WPS_FAIL_REASON_RECV_M2D); - } - } - if (sm->ignore_sel_reg) { - esp_wifi_disconnect(); - wps_add_discard_ap(sm->bssid); - os_bzero(sm->creds, sizeof(sm->creds)); - os_bzero(sm->bssid, ETH_ALEN); - sm->discover_ssid_cnt = 0; - wifi_wps_scan(NULL, NULL); + wpa_printf(MSG_ERROR, "WPS: Timed out waiting for M2/M2D"); + wps_handle_failure(WPS_FAIL_REASON_RECV_M2D); } } -void wifi_station_wps_msg_timeout(void *data, void *user_ctx) +static void wifi_station_wps_success(void *data, void *user_ctx) { -#ifdef USE_WPS_TASK - wps_post(SIG_WPS_TIMER_MSG_TIMEOUT, 0); - return; -#else - wifi_station_wps_msg_timeout_internal(); -#endif -} - -void wifi_station_wps_success_internal(void) -{ - wifi_event_sta_wps_er_success_t evt = {0}; - struct wps_sm *sm = gWpsSm; - int i; - /* * For only one AP credential don't send event data, wps_finish() has already set * the config. This is for backward compatibility. */ - if (sm->ap_cred_cnt > 1) { - evt.ap_cred_cnt = sm->ap_cred_cnt; - for (i = 0; i < MAX_WPS_AP_CRED; i++) { - os_memcpy(evt.ap_cred[i].ssid, sm->creds[i].ssid, sm->creds[i].ssid_len); - os_memcpy(evt.ap_cred[i].passphrase, sm->creds[i].key, sm->creds[i].key_len); - } - esp_event_post(WIFI_EVENT, WIFI_EVENT_STA_WPS_ER_SUCCESS, &evt, - sizeof(evt), OS_BLOCK); + if (s_wps_success_evt.ap_cred_cnt > 1) { + esp_event_post(WIFI_EVENT, WIFI_EVENT_STA_WPS_ER_SUCCESS, &s_wps_success_evt, + sizeof(s_wps_success_evt), OS_BLOCK); } else { esp_event_post(WIFI_EVENT, WIFI_EVENT_STA_WPS_ER_SUCCESS, - 0, 0, OS_BLOCK); + 0, 0, OS_BLOCK); } -} - -void wifi_station_wps_success(void *data, void *user_ctx) -{ -#ifdef USE_WPS_TASK - wps_post(SIG_WPS_TIMER_SUCCESS_CB, 0); - return; -#else - wifi_station_wps_success_internal(); -#endif -} - -void wifi_station_wps_eapol_start_handle_internal(void) -{ - wpa_printf(MSG_DEBUG, "Resend EAPOL-Start."); - wps_tx_start(); + os_memset(&s_wps_success_evt, 0, sizeof(s_wps_success_evt)); } void wifi_station_wps_eapol_start_handle(void *data, void *user_ctx) { -#ifdef USE_WPS_TASK - wps_post(SIG_WPS_TIMER_EAPOL_START, 0); - return; -#else - wifi_station_wps_eapol_start_handle_internal(); -#endif + wpa_printf(MSG_DEBUG, "WPS: Resending EAPOL-Start"); + wps_tx_start(); } static int save_credentials_cb(void *ctx, const struct wps_credential *cred) { + struct wps_sm *sm = wps_sm_get(); struct wps_credential *creds; - if (!gWpsSm || !cred || gWpsSm->ap_cred_cnt >= MAX_CRED_COUNT) { + if (!sm || !cred || sm->ap_cred_cnt >= MAX_CRED_COUNT) { return ESP_FAIL; } - creds = &gWpsSm->creds[gWpsSm->ap_cred_cnt]; + creds = &sm->creds[sm->ap_cred_cnt]; memcpy(creds, cred, sizeof(*creds)); - gWpsSm->ap_cred_cnt++; + sm->ap_cred_cnt++; - wpa_hexdump_ascii(MSG_DEBUG, "ssid ", cred->ssid, cred->ssid_len); - wpa_hexdump_ascii(MSG_DEBUG, "key ", cred->key, cred->key_len); + wpa_hexdump_ascii(MSG_DEBUG, "WPS: Received credential - SSID ", cred->ssid, cred->ssid_len); + wpa_hexdump_ascii(MSG_DEBUG, "WPS: Received credential - Key ", cred->key, cred->key_len); return ESP_OK; } @@ -1426,8 +1146,8 @@ int wps_init_cfg_pin(struct wps_config *cfg) cfg->pin_len = 8; if (wps_generate_pin(&spin) < 0) { return -1; - } - wpa_printf(MSG_INFO, "Provided PIN %s is not valid, generated a new PIN %08d", (char *)cfg->pin, spin); + } + wpa_printf(MSG_INFO, "WPS: Invalid PIN provided, generated new PIN: %08d", spin); os_snprintf((char *)cfg->pin, 9, "%08d", spin); } @@ -1449,7 +1169,7 @@ static int wifi_station_wps_init(const esp_wps_config_t *config) goto _out; } - wpa_printf(MSG_DEBUG, "wifi sta wps init"); + wpa_printf(MSG_DEBUG, "WPS: Initializing"); gWpsSm = os_zalloc(sizeof(struct wps_sm)); /* alloc Wps_sm */ if (!gWpsSm) { @@ -1493,37 +1213,33 @@ static int wifi_station_wps_init(const esp_wps_config_t *config) } sm->wps->wps->cred_cb = save_credentials_cb; - /**************80211 reference***************/ - if (esp_wifi_get_appie_internal(WIFI_APPIE_WPS_PR) == NULL) { /* alloc probe req wps ie */ + if (esp_wifi_get_appie_internal(WIFI_APPIE_WPS_PR) == NULL) { wps_build_ic_appie_wps_pr(); } - if (esp_wifi_get_appie_internal(WIFI_APPIE_WPS_AR) == NULL) { /* alloc assoc req wps ie */ + if (esp_wifi_get_appie_internal(WIFI_APPIE_WPS_AR) == NULL) { wps_build_ic_appie_wps_ar(); } - eloop_cancel_timeout(wifi_station_wps_timeout, NULL, NULL); - eloop_cancel_timeout(wifi_station_wps_msg_timeout, NULL, NULL); - eloop_cancel_timeout(wifi_station_wps_success, NULL, NULL); - eloop_cancel_timeout(wifi_wps_scan, NULL, NULL); - eloop_cancel_timeout(wifi_station_wps_eapol_start_handle, NULL, NULL); + /* Cancel any pending timers from previous WPS attempts */ + wps_delete_timer(); wps_cb = os_malloc(sizeof(struct wps_funcs)); if (wps_cb == NULL) { goto _err; } wps_cb->wps_parse_scan_result = wps_parse_scan_result; - wps_cb->wifi_station_wps_start = wifi_station_wps_start; + wps_cb->wifi_station_wps_start = NULL; wps_cb->wps_sm_rx_eapol = wps_sm_rx_eapol; wps_cb->wps_start_pending = wps_start_pending; esp_wifi_set_wps_cb_internal(wps_cb); - s_wps_sm_cb = os_malloc(sizeof(struct wps_sm_funcs)); - if (s_wps_sm_cb == NULL) { + s_wps_sm_cb = os_zalloc(sizeof(struct wps_sm_funcs)); + if (!s_wps_sm_cb) { goto _err; } - s_wps_sm_cb->wps_sm_notify_deauth = wps_sm_notify_deauth; + os_memset(&s_wps_success_evt, 0, sizeof(s_wps_success_evt)); return ESP_OK; @@ -1553,9 +1269,9 @@ _out: return ESP_FAIL; } -int wps_delete_timer(void) +static int wps_delete_timer(void) { - struct wps_sm *sm = gWpsSm; + struct wps_sm *sm = wps_sm_get(); if (!sm) { return ESP_OK; @@ -1566,12 +1282,12 @@ int wps_delete_timer(void) eloop_cancel_timeout(wifi_station_wps_msg_timeout, NULL, NULL); eloop_cancel_timeout(wifi_wps_scan, NULL, NULL); eloop_cancel_timeout(wifi_station_wps_eapol_start_handle, NULL, NULL); + eloop_cancel_timeout(wifi_station_wps_post_m8_timeout, NULL, NULL); esp_wifi_disarm_sta_connection_timer_internal(); return ESP_OK; } -int -wifi_station_wps_deinit(void) +static int wifi_station_wps_deinit(void) { struct wps_sm *sm = gWpsSm; @@ -1609,16 +1325,14 @@ wifi_station_wps_deinit(void) return ESP_OK; } -struct wps_sm * -wps_sm_get(void) +struct wps_sm *wps_sm_get(void) { return gWpsSm; } -void -wifi_wps_scan_done(void *arg, ETS_STATUS status) +static void wifi_wps_scan_done(void *arg, ETS_STATUS status) { - struct wps_sm *sm = gWpsSm; + struct wps_sm *sm = wps_sm_get(); wifi_config_t wifi_config = {0}; wpa_printf(MSG_INFO, "WPS: scan done"); @@ -1637,22 +1351,19 @@ wifi_wps_scan_done(void *arg, ETS_STATUS status) } else { if (sm->wps_pbc_overlap) { sm->wps_pbc_overlap = false; - wpa_printf(MSG_INFO, "PBC session overlap!"); - wps_set_status(WPS_STATUS_DISABLE); - esp_event_post(WIFI_EVENT, WIFI_EVENT_STA_WPS_ER_PBC_OVERLAP, 0, 0, OS_BLOCK); + wpa_printf(MSG_ERROR, "WPS: PBC session overlap detected!"); + wps_send_event_and_disable(WIFI_EVENT_STA_WPS_ER_PBC_OVERLAP, 0, 0); + return; /* WPS is disabled, no further processing */ } else { wps_set_status(WPS_STATUS_PENDING); } } - wpa_printf(MSG_DEBUG, "wps scan_done discover_ssid_cnt = %d", sm->discover_ssid_cnt); + wpa_printf(MSG_DEBUG, "WPS: Scan done, %d APs discovered.", sm->discover_ssid_cnt); sm->discover_ssid_cnt = 0; if (wps_get_status() == WPS_STATUS_PENDING) { - sm->intermediate_disconnect = true; - esp_wifi_disconnect(); - sm->intermediate_disconnect = false; os_memcpy(wifi_config.sta.bssid, sm->bssid, ETH_ALEN); os_memcpy(wifi_config.sta.ssid, (char *)sm->creds[0].ssid, sm->creds[0].ssid_len); @@ -1662,62 +1373,68 @@ wifi_wps_scan_done(void *arg, ETS_STATUS status) (char *)sm->creds[0].ssid, MAC2STR(wifi_config.sta.bssid)); esp_wifi_set_config(0, &wifi_config); - wpa_printf(MSG_DEBUG, "WPS: neg start"); + wpa_printf(MSG_DEBUG, "WPS: Starting negotiation"); wifi_config.sta.failure_retry_cnt = 2; esp_wifi_connect(); sm->state = WAIT_START; eloop_cancel_timeout(wifi_station_wps_msg_timeout, NULL, NULL); - eloop_register_timeout(20, 0, wifi_station_wps_msg_timeout, NULL, NULL); + eloop_register_timeout(WPS_CONNECT_TIMEOUT_SECS, 0, wifi_station_wps_msg_timeout, NULL, NULL); } else if (wps_get_status() == WPS_STATUS_SCANNING) { - if (wps_get_type() == WPS_TYPE_PIN && sm->scan_cnt > WPS_IGNORE_SEL_REG_MAX_CNT) { - wpa_printf(MSG_INFO, "WPS: ignore selected registrar after %d scans", sm->scan_cnt); - sm->ignore_sel_reg = true; - } eloop_cancel_timeout(wifi_wps_scan, NULL, NULL); - eloop_register_timeout(2, 0, wifi_wps_scan, NULL, NULL); + eloop_register_timeout(WPS_SCAN_RETRY_TIMEOUT_SECS, 0, wifi_wps_scan, NULL, NULL); } else { return; } } -void -wifi_wps_scan_internal(void) +static void wifi_wps_scan(void *data, void *user_ctx) { - struct wps_sm *sm = gWpsSm; + struct wps_sm *sm = wps_sm_get(); - sm->scan_cnt++; - wpa_printf(MSG_DEBUG, "wifi_wps_scan : %d", sm->scan_cnt); + if (!sm) { + return; + } + + wpa_printf(MSG_DEBUG, "WPS: Starting scan"); typedef void (* scan_done_cb_t)(void *arg, ETS_STATUS status); extern int esp_wifi_promiscuous_scan_start(wifi_scan_config_t *config, scan_done_cb_t cb); esp_wifi_promiscuous_scan_start(NULL, wifi_wps_scan_done); } -void wifi_wps_scan(void *data, void *user_ctx) -{ -#ifdef USE_WPS_TASK - wps_post(SIG_WPS_TIMER_SCAN, 0); - return; -#else - wifi_wps_scan_internal(); -#endif -} - static int wps_rf_band_cb(void *ctx) { - return WPS_RF_24GHZ; + wifi_band_mode_t band_mode; + esp_err_t ret = esp_wifi_get_band_mode(&band_mode); + + if (ret != ESP_OK) { + wpa_printf(MSG_ERROR, "WPS: failed to get band mode"); + } + + switch (band_mode) { + case WIFI_BAND_MODE_2G_ONLY: + return WPS_RF_24GHZ; + case WIFI_BAND_MODE_5G_ONLY: + return WPS_RF_50GHZ; + case WIFI_BAND_MODE_AUTO: + return WPS_RF_24GHZ | WPS_RF_50GHZ; + default: + return WPS_RF_24GHZ; + } + return WPS_RF_24GHZ; } -int wifi_station_wps_start(void) +static int wifi_station_wps_start(void *data, void *user_ctx) { struct wps_sm *sm = wps_sm_get(); if (!sm) { - wpa_printf(MSG_ERROR, "WPS: wps is not initialized"); + wpa_printf(MSG_ERROR, "WPS: Not initialized"); return ESP_FAIL; } - eloop_register_timeout(120, 0, wifi_station_wps_timeout, NULL, NULL); + eloop_cancel_timeout(wifi_station_wps_timeout, NULL, NULL); + eloop_register_timeout(WPS_TOTAL_TIMEOUT_SECS, 0, wifi_station_wps_timeout, NULL, NULL); switch (wps_get_status()) { case WPS_STATUS_DISABLE: @@ -1732,140 +1449,54 @@ int wifi_station_wps_start(void) sm->wps->wps->dh_pubkey = sm->wps->dh_pubkey_e; sm->wps->wps->rf_band_cb = wps_rf_band_cb; sm->wps->dh_privkey = NULL; +#ifdef CONFIG_WPS_RECONNECT_ON_FAIL + if (s_previous_wifi_config) { + os_free(s_previous_wifi_config); + s_previous_wifi_config = NULL; + } + wifi_ap_record_t ap_info; + /* Check if we are connected to an AP */ + if (esp_wifi_sta_get_ap_info(&ap_info) == ESP_OK) { + s_previous_wifi_config = (wifi_config_t *)os_zalloc(sizeof(wifi_config_t)); + if (s_previous_wifi_config) { + if (esp_wifi_get_config(WIFI_IF_STA, s_previous_wifi_config) != ESP_OK || + s_previous_wifi_config->sta.ssid[0] == 0) { + os_free(s_previous_wifi_config); + s_previous_wifi_config = NULL; + } else { + wpa_printf(MSG_INFO, "WPS: Stored previous AP to reconnect on failure: %s", + (char *)s_previous_wifi_config->sta.ssid); + } + } + } +#endif esp_wifi_disconnect(); wifi_wps_scan(NULL, NULL); + if (s_wps_sm_cb) { + s_wps_sm_cb->wps_sm_notify_deauth = wps_sm_notify_deauth; + } break; case WPS_STATUS_SCANNING: - sm->scan_cnt = 0; eloop_cancel_timeout(wifi_station_wps_timeout, NULL, NULL); - eloop_register_timeout(120, 0, wifi_station_wps_timeout, NULL, NULL); + eloop_register_timeout(WPS_TOTAL_TIMEOUT_SECS, 0, wifi_station_wps_timeout, NULL, NULL); break; default: break; } os_memset(sm->uuid_r, 0, sizeof(sm->uuid_r)); sm->wps_pbc_overlap = false; - sm->discard_ap_cnt = 0; - os_memset(&sm->dis_ap_list, 0, WPS_MAX_DIS_AP_NUM * sizeof(struct discard_ap_list_t)); esp_wifi_set_wps_start_flag_internal(true); return ESP_OK; } -int wps_task_deinit(void) -{ - wpa_printf(MSG_DEBUG, "wps task deinit"); - - if (s_wps_api_sem) { - os_semphr_delete(s_wps_api_sem); - s_wps_api_sem = NULL; - wpa_printf(MSG_DEBUG, "wps task deinit: free api sem"); - } - - if (s_wps_task_create_sem) { - os_semphr_delete(s_wps_task_create_sem); - s_wps_task_create_sem = NULL; - wpa_printf(MSG_DEBUG, "wps task deinit: free task create sem"); - } - - if (s_wps_queue) { - os_queue_delete(s_wps_queue); - s_wps_queue = NULL; - wpa_printf(MSG_DEBUG, "wps task deinit: free queue"); - } - - if (STAILQ_FIRST(&s_wps_rxq) != NULL){ - wps_rxq_deinit(); - } - - if (s_wps_data_lock) { - os_mutex_delete(s_wps_data_lock); - s_wps_data_lock = NULL; - } - - return ESP_OK; -} - -int wps_task_init(void) -{ - int ret = 0; - - /* Call wps_task_deinit() first in case esp_wifi_wps_disable() fails - */ - wps_task_deinit(); - - if (!s_wps_data_lock) { - s_wps_data_lock = os_recursive_mutex_create(); - if (!s_wps_data_lock) { - wpa_printf(MSG_ERROR, "wps task init: failed to alloc data lock"); - goto _wps_no_mem; - } - } - - s_wps_api_sem = os_semphr_create(1, 0); - if (!s_wps_api_sem) { - wpa_printf(MSG_ERROR, "wps task init: failed to create api sem"); - goto _wps_no_mem; - } - - s_wps_task_create_sem = os_semphr_create(1, 0); - if (!s_wps_task_create_sem) { - wpa_printf(MSG_ERROR, "wps task init: failed to create task sem"); - goto _wps_no_mem; - } - - os_bzero(s_wps_sig_cnt, SIG_WPS_NUM); - s_wps_queue = os_queue_create(SIG_WPS_NUM, sizeof(ETSEvent)); - if (!s_wps_queue) { - wpa_printf(MSG_ERROR, "wps task init: failed to alloc queue"); - goto _wps_no_mem; - } - - wps_rxq_init(); - - ret = os_task_create(wps_task, "wpsT", WPS_TASK_STACK_SIZE, NULL, 2, &s_wps_task_hdl); - if (TRUE != ret) { - wpa_printf(MSG_ERROR, "wps enable: failed to create task"); - goto _wps_no_mem; - } - - os_semphr_take(s_wps_task_create_sem, OS_BLOCK); - os_semphr_delete(s_wps_task_create_sem); - s_wps_task_create_sem = NULL; - - wpa_printf(MSG_DEBUG, "wifi wps enable: task prio:%d, stack:%d", 2, WPS_TASK_STACK_SIZE); - return ESP_OK; - -_wps_no_mem: - wps_task_deinit(); - return ESP_ERR_NO_MEM; -} - -int wps_post_block(uint32_t sig, void *arg) -{ - wps_ioctl_param_t param; - - param.ret = ESP_FAIL; - param.arg = arg; - - if (ESP_OK != wps_post(sig, (uint32_t)¶m)) { - return ESP_FAIL; - } - - if (TRUE == os_semphr_take(s_wps_api_sem, OS_BLOCK)) { - return param.ret; - } else { - return ESP_FAIL; - } -} - -int wps_check_wifi_mode(void) +static int wps_check_wifi_mode(void) { wifi_mode_t mode; int ret; ret = esp_wifi_get_mode(&mode); if (ESP_OK != ret) { - wpa_printf(MSG_ERROR, "wps check wifi mode: failed to get wifi mode ret=%d", ret); + wpa_printf(MSG_ERROR, "WPS: Failed to get Wi-Fi mode (ret=%d)", ret); return ESP_FAIL; } @@ -1874,7 +1505,7 @@ int wps_check_wifi_mode(void) mode == WIFI_MODE_AP || #endif mode == WIFI_MODE_NULL) { - wpa_printf(MSG_ERROR, "wps check wifi mode: wrong wifi mode=%d ", mode); + wpa_printf(MSG_ERROR, "WPS: Invalid Wi-Fi mode for WPS: %d ", mode); return ESP_ERR_WIFI_MODE; } @@ -1887,7 +1518,7 @@ int esp_wifi_wps_enable(const esp_wps_config_t *config) struct wps_sm *sm = gWpsSm; if (esp_wifi_get_user_init_flag_internal() == 0) { - wpa_printf(MSG_ERROR, "wps enable: wifi not started cannot disable wpsreg"); + wpa_printf(MSG_ERROR, "WPS: Wi-Fi not started, cannot enable"); return ESP_ERR_WIFI_STATE; } @@ -1896,69 +1527,64 @@ int esp_wifi_wps_enable(const esp_wps_config_t *config) } if (is_dpp_enabled()) { - wpa_printf(MSG_ERROR, "wps enabled failed since DPP is initialized"); + wpa_printf(MSG_ERROR, "WPS: Cannot enable, DPP is already initialized"); return ESP_FAIL; } API_MUTEX_TAKE(); if (s_wps_enabled) { if (sm && os_memcmp(sm->identity, WSC_ID_REGISTRAR, sm->identity_len) == 0) { - wpa_printf(MSG_ERROR, "wps enable: wpsreg already enabled cannot enable wps enrollee"); + wpa_printf(MSG_ERROR, "WPS: Cannot enable Enrollee, Registrar is already enabled"); ret = ESP_ERR_WIFI_MODE; } else { - wpa_printf(MSG_DEBUG, "wps enable: already enabled"); + wpa_printf(MSG_DEBUG, "WPS: Already enabled"); } API_MUTEX_GIVE(); return ret; } -#ifdef USE_WPS_TASK - ret = wps_task_init(); - if (ESP_OK != ret) { - API_MUTEX_GIVE(); - return ret; - } - - ret = wps_post_block(SIG_WPS_ENABLE, (esp_wps_config_t *)config); - if (ESP_OK != ret) { - wps_task_deinit(); - API_MUTEX_GIVE(); - return ret; - } - + ret = eloop_register_timeout_blocking(wifi_wps_enable_internal, NULL, (void *)config); s_wps_enabled = true; - wpa_printf(MSG_DEBUG, "wifi wps task: prio:%d, stack:%d", 2, WPS_TASK_STACK_SIZE); API_MUTEX_GIVE(); return ret; -#else - ret = wifi_wps_enable_internal(config); - API_MUTEX_GIVE(); - return ret; -#endif } bool is_wps_enabled(void) { - return s_wps_enabled; + bool enabled; + + API_MUTEX_TAKE(); + enabled = s_wps_enabled; + API_MUTEX_GIVE(); + + return enabled; } -int wifi_wps_enable_internal(const esp_wps_config_t *config) +static int wifi_wps_disable(void) { + wps_set_type(WPS_TYPE_DISABLE); + wifi_wps_disable_internal(NULL, NULL); + + return 0; +} + +static int wifi_wps_enable_internal(void *ctx, void *data) +{ + const esp_wps_config_t *config = (const esp_wps_config_t *)data; int ret = 0; struct wpa_sm *wpa_sm = &gWpaSm; - wpa_printf(MSG_DEBUG, "ESP WPS crypto initialize!"); if (config->wps_type == WPS_TYPE_DISABLE) { - wpa_printf(MSG_ERROR, "wps enable: invalid wps type"); + wpa_printf(MSG_ERROR, "WPS: Invalid WPS type for enabling"); return ESP_ERR_WIFI_WPS_TYPE; } - wpa_printf(MSG_DEBUG, "Set factory information."); + wpa_printf(MSG_DEBUG, "WPS: Setting factory information"); ret = wps_set_factory_info(config); if (ret != 0) { return ret; } - wpa_printf(MSG_INFO, "wifi_wps_enable"); + wpa_printf(MSG_INFO, "WPS: Enabling"); wps_set_type(config->wps_type); wps_set_status(WPS_STATUS_DISABLE); @@ -1970,12 +1596,16 @@ int wifi_wps_enable_internal(const esp_wps_config_t *config) wps_set_status(WPS_STATUS_DISABLE); return ESP_FAIL; } - wpa_sm->wpa_sm_wps_disable = esp_wifi_wps_disable; + wpa_sm->wpa_sm_wps_disable = wifi_wps_disable; return ESP_OK; } -int wifi_wps_disable_internal(void) +static int wifi_wps_disable_internal(void *ctx, void *data) { + /* Only disconnect in case of WPS pending */ + if (wps_get_status() == WPS_STATUS_PENDING) { + esp_wifi_disconnect(); + } wps_set_status(WPS_STATUS_DISABLE); /* Call wps_delete_timer to delete all WPS timer, no timer will call wps_post() @@ -1983,13 +1613,19 @@ int wifi_wps_disable_internal(void) */ wps_delete_timer(); wifi_station_wps_deinit(); +#ifdef CONFIG_WPS_RECONNECT_ON_FAIL + /* If the config exists, it means WPS was cancelled by the user */ + if (s_previous_wifi_config) { + os_free(s_previous_wifi_config); + s_previous_wifi_config = NULL; + } +#endif return ESP_OK; } int esp_wifi_wps_disable(void) { int ret = 0; - int wps_status; struct wps_sm *wps_sm = gWpsSm; struct wpa_sm *wpa_sm = &gWpaSm; @@ -2000,31 +1636,20 @@ int esp_wifi_wps_disable(void) API_MUTEX_TAKE(); if (!s_wps_enabled) { - wpa_printf(MSG_DEBUG, "wps disable: already disabled"); + wpa_printf(MSG_DEBUG, "WPS: Already disabled"); API_MUTEX_GIVE(); return ESP_OK; } - wps_status = wps_get_status(); - wpa_printf(MSG_INFO, "wifi_wps_disable"); + wpa_printf(MSG_INFO, "WPS: Disabling"); wps_set_type(WPS_TYPE_DISABLE); /* Notify WiFi task */ -#ifdef USE_WPS_TASK - ret = wps_post_block(SIG_WPS_DISABLE, 0); -#else - ret = wifi_wps_disable_internal(); -#endif + ret = eloop_register_timeout_blocking(wifi_wps_disable_internal, NULL, NULL); if (ESP_OK != ret) { - wpa_printf(MSG_ERROR, "wps disable: failed to disable wps, ret=%d", ret); - } - - /* Only disconnect in case of WPS pending/done */ - if ((wps_status == WPS_STATUS_PENDING) || (wps_status == WPS_STATUS_SUCCESS)) { - esp_wifi_disconnect(); + wpa_printf(MSG_ERROR, "WPS: Failed to disable (ret=%d)", ret); } esp_wifi_set_wps_start_flag_internal(false); - wps_task_deinit(); s_wps_enabled = false; API_MUTEX_GIVE(); wpa_sm->wpa_sm_wps_disable = NULL; @@ -2033,6 +1658,8 @@ int esp_wifi_wps_disable(void) int esp_wifi_wps_start(int timeout_ms) { + int ret; + if (ESP_OK != wps_check_wifi_mode()) { return ESP_ERR_WIFI_MODE; } @@ -2040,27 +1667,17 @@ int esp_wifi_wps_start(int timeout_ms) API_MUTEX_TAKE(); if (!s_wps_enabled) { - wpa_printf(MSG_ERROR, "wps start: wps not enabled"); + wpa_printf(MSG_ERROR, "WPS: Cannot start, not enabled"); API_MUTEX_GIVE(); return ESP_ERR_WIFI_WPS_SM; } - if (wps_get_type() == WPS_TYPE_DISABLE || (wps_get_status() != WPS_STATUS_DISABLE && wps_get_status() != WPS_STATUS_SCANNING)) { - API_MUTEX_GIVE(); - return ESP_ERR_WIFI_WPS_TYPE; - } - if (esp_wifi_get_user_init_flag_internal() == 0) { API_MUTEX_GIVE(); return ESP_ERR_WIFI_STATE; } - wpa_printf(MSG_DEBUG, "wps scan"); -#ifdef USE_WPS_TASK - wps_post_block(SIG_WPS_START, 0); -#else - ic_pp_post(SIG_PP_WPS, 0); -#endif + ret = eloop_register_timeout_blocking(wifi_station_wps_start, NULL, NULL); API_MUTEX_GIVE(); - return ESP_OK; + return ret; } diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_wps_i.h b/components/wpa_supplicant/esp_supplicant/src/esp_wps_i.h index 1058da26b7..d32b1c4334 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wps_i.h +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wps_i.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -15,21 +15,6 @@ enum wps_msg_flag { WPS_MSG_FLAG_LEN = 0x02 }; -#ifdef USE_WPS_TASK -enum wps_sig_type { - SIG_WPS_ENABLE = 1, //1 - SIG_WPS_DISABLE, //2 - SIG_WPS_START, //3 - SIG_WPS_RX, //4 - SIG_WPS_TIMER_TIMEOUT, //5 - SIG_WPS_TIMER_MSG_TIMEOUT, //6 - SIG_WPS_TIMER_SUCCESS_CB, //7 - SIG_WPS_TIMER_SCAN, //8 - SIG_WPS_TIMER_EAPOL_START, //9 - SIG_WPS_NUM, //10 -}; -#endif - enum wps_reg_sig_type { SIG_WPS_REG_ENABLE = 1, //1 SIG_WPS_REG_DISABLE, //2 @@ -50,10 +35,6 @@ enum wps_sm_state { }; #endif /* ESP_SUPPLICANT */ -#define WPS_IGNORE_SEL_REG_MAX_CNT 10 - -#define WPS_MAX_DIS_AP_NUM 10 - /* Bssid of the discard AP which is discarded for not select reg or other reason */ struct discard_ap_list_t { u8 bssid[6]; @@ -76,16 +57,9 @@ struct wps_sm { u8 current_identifier; bool is_wps_scan; u8 channel; - u8 scan_cnt; -#ifdef USE_WPS_TASK - u8 wps_sig_cnt[SIG_WPS_NUM]; -#endif u8 discover_ssid_cnt; - bool ignore_sel_reg; bool wps_pbc_overlap; - struct discard_ap_list_t dis_ap_list[WPS_MAX_DIS_AP_NUM]; - u8 discard_ap_cnt; - bool intermediate_disconnect; + bool post_m8_recv; }; #define API_MUTEX_TAKE() do {\ @@ -105,8 +79,6 @@ struct wps_sm { struct wps_sm *wps_sm_get(void); int wps_station_wps_unregister_cb(void); -int wps_start_pending(void); -int wps_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len); int wps_dev_deinit(struct wps_device_data *dev); int wps_dev_init(void); diff --git a/examples/wifi/wps/main/wps.c b/examples/wifi/wps/main/wps.c index 8ba96a3c20..882a1f7201 100644 --- a/examples/wifi/wps/main/wps.c +++ b/examples/wifi/wps/main/wps.c @@ -7,27 +7,28 @@ CONDITIONS OF ANY KIND, either express or implied. */ -/* - This example demonstrates how to use WPS. - It supports two modes, which can be selected in menuconfig. - - WPS_TYPE_PBC: - Start ESP32 and it will enter WPS PBC mode. Then push WPS button on the router. - ESP32 will receive SSID and password, and connect to the router. - - WPS_TYPE_PIN: - Start ESP32, you'll see an eight-digit PIN number in log output. - Enter the PIN code on the router and then the ESP32 will get connected to router. -*/ - +/** + * @brief Demonstrates how to use WPS. + * + * This example supports two modes, which can be selected in menuconfig: + * + * - WPS_TYPE_PBC: + * Start the ESP device and it will enter WPS PBC mode. Then push the WPS button on the router. + * The ESP device will receive the SSID and password and connect to the router. + * + * - WPS_TYPE_PIN: + * Start the ESP device, and you'll see an eight-digit PIN number in the log output. + * Enter this PIN code on the router, and the ESP device will connect. + * + */ +#include #include "freertos/FreeRTOS.h" #include "freertos/event_groups.h" -#include "esp_wifi.h" -#include "esp_log.h" -#include "esp_wps.h" #include "esp_event.h" +#include "esp_log.h" +#include "esp_wifi.h" +#include "esp_wps.h" #include "nvs_flash.h" -#include /*set wps mode via project configuration */ @@ -48,9 +49,50 @@ static const char *TAG = "example_wps"; static esp_wps_config_t config = WPS_CONFIG_INIT_DEFAULT(WPS_MODE); -static wifi_config_t wps_ap_creds[MAX_WPS_AP_CRED]; +static wifi_config_t s_wps_ap_creds[MAX_WPS_AP_CRED]; static int s_ap_creds_num = 0; static int s_retry_num = 0; +static bool s_wps_done = false; + +static void wps_restart(void) +{ + ESP_ERROR_CHECK(esp_wifi_wps_disable()); + ESP_ERROR_CHECK(esp_wifi_wps_enable(&config)); + ESP_ERROR_CHECK(esp_wifi_wps_start(0)); +} + +static void handle_wps_success(void *event_data) +{ + wifi_event_sta_wps_er_success_t *evt = (wifi_event_sta_wps_er_success_t *)event_data; + if (evt) { + s_ap_creds_num = evt->ap_cred_cnt; + for (int idx = 0; idx < s_ap_creds_num; idx++) { + memcpy(s_wps_ap_creds[idx].sta.ssid, evt->ap_cred[idx].ssid, + sizeof(evt->ap_cred[idx].ssid)); + memcpy(s_wps_ap_creds[idx].sta.password, evt->ap_cred[idx].passphrase, + sizeof(evt->ap_cred[idx].passphrase)); + } + /* If multiple AP credentials are received from WPS, connect with first one */ + ESP_LOGI(TAG, "Connecting to SSID: %s, Passphrase: %s", + s_wps_ap_creds[0].sta.ssid, s_wps_ap_creds[0].sta.password); + ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &s_wps_ap_creds[0])); + } + /* + * If only one AP credential is received from WPS, there will be no event data and + * esp_wifi_set_config() is already called by WPS modules for backward compatibility + * with legacy apps. So directly attempt connection here. + */ + ESP_ERROR_CHECK(esp_wifi_wps_disable()); + s_wps_done = true; + esp_wifi_connect(); +} + +static void handle_wps_pin(void *event_data) +{ + /* display the PIN code */ + wifi_event_sta_wps_er_pin_t* event = (wifi_event_sta_wps_er_pin_t*) event_data; + ESP_LOGI(TAG, "WPS_PIN = " PINSTR, PIN2STR(event->pin_code)); +} static void wifi_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) @@ -58,78 +100,46 @@ static void wifi_event_handler(void* arg, esp_event_base_t event_base, static int ap_idx = 1; switch (event_id) { - case WIFI_EVENT_STA_START: - ESP_LOGI(TAG, "WIFI_EVENT_STA_START"); - break; - case WIFI_EVENT_STA_DISCONNECTED: - ESP_LOGI(TAG, "WIFI_EVENT_STA_DISCONNECTED"); + case WIFI_EVENT_STA_START: + ESP_LOGI(TAG, "WIFI_EVENT_STA_START"); + break; + case WIFI_EVENT_STA_DISCONNECTED: + ESP_LOGI(TAG, "WIFI_EVENT_STA_DISCONNECTED"); + if (s_wps_done) { if (s_retry_num < MAX_RETRY_ATTEMPTS) { esp_wifi_connect(); s_retry_num++; + ESP_LOGI(TAG, "retrying to connect to the AP"); } else if (ap_idx < s_ap_creds_num) { /* Try the next AP credential if first one fails */ - - if (ap_idx < s_ap_creds_num) { - ESP_LOGI(TAG, "Connecting to SSID: %s, Passphrase: %s", - wps_ap_creds[ap_idx].sta.ssid, wps_ap_creds[ap_idx].sta.password); - ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wps_ap_creds[ap_idx++]) ); - esp_wifi_connect(); - } + ESP_LOGI(TAG, "Connecting to SSID: %s, Passphrase: %s", + s_wps_ap_creds[ap_idx].sta.ssid, s_wps_ap_creds[ap_idx].sta.password); + ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &s_wps_ap_creds[ap_idx++])); + esp_wifi_connect(); s_retry_num = 0; } else { ESP_LOGI(TAG, "Failed to connect!"); } - - break; - case WIFI_EVENT_STA_WPS_ER_SUCCESS: - ESP_LOGI(TAG, "WIFI_EVENT_STA_WPS_ER_SUCCESS"); - { - wifi_event_sta_wps_er_success_t *evt = - (wifi_event_sta_wps_er_success_t *)event_data; - int i; - - if (evt) { - s_ap_creds_num = evt->ap_cred_cnt; - for (i = 0; i < s_ap_creds_num; i++) { - memcpy(wps_ap_creds[i].sta.ssid, evt->ap_cred[i].ssid, - sizeof(evt->ap_cred[i].ssid)); - memcpy(wps_ap_creds[i].sta.password, evt->ap_cred[i].passphrase, - sizeof(evt->ap_cred[i].passphrase)); - } - /* If multiple AP credentials are received from WPS, connect with first one */ - ESP_LOGI(TAG, "Connecting to SSID: %s, Passphrase: %s", - wps_ap_creds[0].sta.ssid, wps_ap_creds[0].sta.password); - ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wps_ap_creds[0]) ); - } - /* - * If only one AP credential is received from WPS, there will be no event data and - * esp_wifi_set_config() is already called by WPS modules for backward compatibility - * with legacy apps. So directly attempt connection here. - */ - ESP_ERROR_CHECK(esp_wifi_wps_disable()); - esp_wifi_connect(); - } - break; - case WIFI_EVENT_STA_WPS_ER_FAILED: - ESP_LOGI(TAG, "WIFI_EVENT_STA_WPS_ER_FAILED"); - ESP_ERROR_CHECK(esp_wifi_wps_disable()); - ESP_ERROR_CHECK(esp_wifi_wps_enable(&config)); - ESP_ERROR_CHECK(esp_wifi_wps_start(0)); - break; - case WIFI_EVENT_STA_WPS_ER_TIMEOUT: - ESP_LOGI(TAG, "WIFI_EVENT_STA_WPS_ER_TIMEOUT"); - ESP_ERROR_CHECK(esp_wifi_wps_disable()); - ESP_ERROR_CHECK(esp_wifi_wps_enable(&config)); - ESP_ERROR_CHECK(esp_wifi_wps_start(0)); - break; - case WIFI_EVENT_STA_WPS_ER_PIN: - ESP_LOGI(TAG, "WIFI_EVENT_STA_WPS_ER_PIN"); - /* display the PIN code */ - wifi_event_sta_wps_er_pin_t* event = (wifi_event_sta_wps_er_pin_t*) event_data; - ESP_LOGI(TAG, "WPS_PIN = " PINSTR, PIN2STR(event->pin_code)); - break; - default: - break; + } + break; + case WIFI_EVENT_STA_WPS_ER_SUCCESS: + ESP_LOGI(TAG, "WIFI_EVENT_STA_WPS_ER_SUCCESS"); + handle_wps_success(event_data); + break; + case WIFI_EVENT_STA_WPS_ER_FAILED: + ESP_LOGI(TAG, "WIFI_EVENT_STA_WPS_ER_FAILED"); + wps_restart(); + break; + case WIFI_EVENT_STA_WPS_ER_TIMEOUT: + ESP_LOGI(TAG, "WIFI_EVENT_STA_WPS_ER_TIMEOUT"); + wps_restart(); + break; + case WIFI_EVENT_STA_WPS_ER_PIN: + ESP_LOGI(TAG, "WIFI_EVENT_STA_WPS_ER_PIN"); + handle_wps_pin(event_data); + break; + default: + break; } } @@ -140,7 +150,9 @@ static void got_ip_event_handler(void* arg, esp_event_base_t event_base, ESP_LOGI(TAG, "got ip: " IPSTR, IP2STR(&event->ip_info.ip)); } -/*init wifi as sta and start wps*/ +/** + * @brief Start WPS registration + */ static void start_wps(void) { ESP_ERROR_CHECK(esp_netif_init());