Kaynağa Gözat

WiFi: Add WPS softAP registrar example and events

Kapil Gupta 3 yıl önce
ebeveyn
işleme
924c709efe

+ 29 - 0
components/esp_wifi/include/esp_wifi_types.h

@@ -646,6 +646,12 @@ typedef enum {
 
     WIFI_EVENT_CONNECTIONLESS_MODULE_WAKE_INTERVAL_START,   /**< ESP32 connectionless module wake interval start */
 
+    WIFI_EVENT_AP_WPS_RG_SUCCESS,       /**< Soft-AP wps succeeds in registrar mode */
+    WIFI_EVENT_AP_WPS_RG_FAILED,        /**< Soft-AP wps fails in registrar mode */
+    WIFI_EVENT_AP_WPS_RG_TIMEOUT,       /**< Soft-AP wps timeout in registrar mode */
+    WIFI_EVENT_AP_WPS_RG_PIN,           /**< Soft-AP wps pin code in registrar mode */
+    WIFI_EVENT_AP_WPS_RG_PBC_OVERLAP,   /**< Soft-AP wps overlap in registrar mode */
+
     WIFI_EVENT_MAX,                      /**< Invalid WiFi event ID */
 } wifi_event_t;
 
@@ -789,6 +795,29 @@ typedef struct {
     uint32_t context;         /**< Context to identify the request */
 } wifi_event_roc_done_t;
 
+/** Argument structure for WIFI_EVENT_AP_WPS_RG_PIN event */
+typedef struct {
+    uint8_t pin_code[8];         /**< PIN code of station in enrollee mode */
+} wifi_event_ap_wps_rg_pin_t;
+
+typedef enum {
+    WPS_AP_FAIL_REASON_NORMAL = 0,     /**< WPS normal fail reason */
+    WPS_AP_FAIL_REASON_CONFIG,         /**< WPS failed due to incorrect config */
+    WPS_AP_FAIL_REASON_AUTH,           /**< WPS failed during auth */
+    WPS_AP_FAIL_REASON_MAX,
+} wps_fail_reason_t;
+
+/** Argument structure for WIFI_EVENT_AP_WPS_RG_FAILED event */
+typedef struct {
+    wps_fail_reason_t reason;          /**< WPS failure reason wps_fail_reason_t */
+    uint8_t peer_macaddr[6];           /**< Enrollee mac address */
+} wifi_event_ap_wps_rg_fail_reason_t;
+
+/** Argument structure for WIFI_EVENT_AP_WPS_RG_SUCCESS event */
+typedef struct {
+    uint8_t peer_macaddr[6];           /**< Enrollee mac address */
+} wifi_event_ap_wps_rg_success_t;
+
 #ifdef __cplusplus
 }
 #endif

+ 1 - 1
components/esp_wifi/lib

@@ -1 +1 @@
-Subproject commit 9e81af17476302dbf053242a9a0a9b81a3cd2949
+Subproject commit 2fae5b132437907691d51ac4b3c31227b7b7ab33

+ 5 - 1
components/wpa_supplicant/esp_supplicant/include/esp_wps.h

@@ -119,7 +119,7 @@ esp_err_t esp_wifi_wps_start(int timeout_ms);
   *
   * @attention WPS can only be used when softAP is enabled.
   *
-  * @param     wps_type_t wps_type : WPS type, so far only WPS_TYPE_PBC and WPS_TYPE_PIN is supported
+  * @param     esp_wps_config_t config: wps configuration to be used.
   *
   * @return
   *          - ESP_OK : succeed
@@ -145,6 +145,10 @@ esp_err_t esp_wifi_ap_wps_disable(void);
   *
   * @attention WPS can only be used when softAP is enabled.
   *
+  * @param  pin : Pin to be used in case of WPS mode is pin.
+  *               If Pin is not provided, device will use the pin generated/provided
+  *               during esp_wifi_ap_wps_enable() and reported in WIFI_EVENT_AP_WPS_RG_PIN
+  *
   * @return
   *          - ESP_OK : succeed
   *          - ESP_ERR_WIFI_WPS_TYPE : wps type is invalid

+ 25 - 8
components/wpa_supplicant/esp_supplicant/src/esp_hostpad_wps.c

@@ -32,7 +32,7 @@ extern void *s_wps_api_lock;
 extern void *s_wps_api_sem;
 extern bool s_wps_enabled;
 
-static int wifi_ap_wps_init(void)
+static int wifi_ap_wps_init(const esp_wps_config_t *config)
 {
     struct wps_sm *sm = NULL;
     uint8_t mac[ETH_ALEN];
@@ -69,6 +69,7 @@ static int wifi_ap_wps_init(void)
     cfg.registrar = 1;
     cfg.wps = sm->wps_ctx;
 
+    os_memcpy((void *)cfg.pin, config->pin, 8);
     wps_init_cfg_pin(&cfg);
     os_memcpy(cfg.wps->uuid, sm->uuid, WPS_UUID_LEN);
     if ((sm->wps = wps_init(&cfg)) == NULL) {         /* alloc wps_data */
@@ -76,6 +77,14 @@ static int wifi_ap_wps_init(void)
     }
 
     hostapd_init_wps(hostapd_get_hapd_data(), sm->wps, sm->wps_ctx);
+
+    /* Report PIN */
+    if (wps_get_type() == WPS_TYPE_PIN) {
+        wifi_event_sta_wps_er_pin_t evt;
+        os_memcpy(evt.pin_code, sm->wps->dev_password, 8);
+        esp_event_post(WIFI_EVENT, WIFI_EVENT_AP_WPS_RG_PIN, &evt, sizeof(evt), OS_BLOCK);
+    }
+
     return ESP_OK;
 
 _err:
@@ -102,23 +111,26 @@ int wifi_ap_wps_deinit(void)
 {
     struct wps_sm *sm = gWpsSm;
 
-    hostapd_deinit_wps(hostapd_get_hapd_data());
     if (gWpsSm == NULL) {
         return ESP_FAIL;
     }
 
+    hostapd_deinit_wps(hostapd_get_hapd_data());
+    if (sm->wps) {
+        sm->wps->registrar = 0;
+        wps_deinit(sm->wps);
+        sm->wps = NULL;
+    }
     if (sm->dev) {
         wps_dev_deinit(sm->dev);
         sm->dev = NULL;
     }
+
     if (sm->wps_ctx) {
         os_free(sm->wps_ctx);
         sm->wps_ctx = NULL;
     }
-    if (sm->wps) {
-        wps_deinit(sm->wps);
-        sm->wps = NULL;
-    }
+
     os_free(gWpsSm);
     gWpsSm = NULL;
 
@@ -146,7 +158,7 @@ int wifi_ap_wps_enable_internal(const esp_wps_config_t *config)
     wps_set_type(config->wps_type);
     wps_set_status(WPS_STATUS_DISABLE);
 
-    ret = wifi_ap_wps_init();
+    ret = wifi_ap_wps_init(config);
 
     if (ret != 0) {
         wps_set_type(WPS_STATUS_DISABLE);
@@ -199,8 +211,8 @@ int esp_wifi_ap_wps_disable(void)
     }
 
     wpa_printf(MSG_INFO, "wifi_wps_disable");
-    wps_set_status(WPS_STATUS_DISABLE);
     wps_set_type(WPS_TYPE_DISABLE);
+    wps_set_status(WPS_STATUS_DISABLE);
 
     wifi_ap_wps_deinit();
 
@@ -232,15 +244,20 @@ int esp_wifi_ap_wps_start(const unsigned char *pin)
     }
 
     if (wps_get_type() == WPS_TYPE_DISABLE || (wps_get_status() != WPS_STATUS_DISABLE && wps_get_status() != WPS_STATUS_SCANNING)) {
+        wpa_printf(MSG_ERROR, "wps start: wps_get_type=%d wps_get_status=%d", wps_get_type(), wps_get_status());
         API_MUTEX_GIVE();
         return ESP_ERR_WIFI_WPS_TYPE;
     }
 
     if (esp_wifi_get_user_init_flag_internal() == 0) {
+        wpa_printf(MSG_ERROR, "wps start: esp_wifi_get_user_init_flag_internal=%d", esp_wifi_get_user_init_flag_internal());
         API_MUTEX_GIVE();
         return ESP_ERR_WIFI_STATE;
     }
 
+    if (!pin) {
+        pin = gWpsSm->wps->dev_password;
+    }
     /* TODO ideally SoftAP mode should also do a single scan in PBC mode
      * however softAP scanning is not available at the moment */
     wps_set_status(WPS_STATUS_PENDING);

+ 8 - 20
components/wpa_supplicant/esp_supplicant/src/esp_wps.c

@@ -1188,22 +1188,7 @@ int wps_dev_deinit(struct wps_device_data *dev)
     if (!dev) {
         return ESP_FAIL;
     }
-
-    if (dev->manufacturer) {
-        os_free(dev->manufacturer);
-    }
-    if (dev->model_name) {
-        os_free(dev->model_name);
-    }
-    if (dev->model_number) {
-        os_free(dev->model_number);
-    }
-    if (dev->device_name) {
-        os_free(dev->device_name);
-    }
-    if (dev->serial_number) {
-        os_free(dev->serial_number);
-    }
+    wps_device_data_free(dev);
 
     if (s_factory_info) {
         os_free(s_factory_info);
@@ -1358,21 +1343,23 @@ int wps_init_cfg_pin(struct wps_config *cfg)
     }
 
     cfg->pbc = 0;
-    if (os_strncmp((char *)cfg->pin, "00000000", 8) != 0) {
+
+    if ((os_strncmp((char *)cfg->pin, "00000000", 8) == 0) || !wps_pin_str_valid((char *)cfg->pin)) {
         unsigned int spin = 0;
+
         cfg->dev_pw_id = DEV_PW_DEFAULT;
         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);
         os_snprintf((char *)cfg->pin, 9, "%08d", spin);
     }
 
     return 0;
 }
 
-int
-wifi_station_wps_init(void)
+static int wifi_station_wps_init(const esp_wps_config_t *config)
 {
     struct wps_funcs *wps_cb;
     struct wps_sm *sm = NULL;
@@ -1408,6 +1395,7 @@ wifi_station_wps_init(void)
 
     cfg.wps = sm->wps_ctx;
 
+    os_memcpy((void *)cfg.pin, config->pin, 8);
     if (wps_init_cfg_pin(&cfg) < 0) {
         goto _err;
     }
@@ -1858,7 +1846,7 @@ int wifi_wps_enable_internal(const esp_wps_config_t *config)
     wps_set_type(config->wps_type);
     wps_set_status(WPS_STATUS_DISABLE);
 
-    ret = wifi_station_wps_init();
+    ret = wifi_station_wps_init(config);
 
     if (ret != 0) {
         wps_set_type(WPS_STATUS_DISABLE);

+ 11 - 3
components/wpa_supplicant/src/ap/sta_info.c

@@ -17,6 +17,7 @@
 #include "wpa_auth.h"
 #include "ap_config.h"
 #include "sta_info.h"
+#include "esp_wps_i.h"
 
 static void ap_sta_delayed_1x_auth_fail_cb(void *eloop_ctx, void *timeout_ctx);
 void hostapd_wps_eap_completed(struct hostapd_data *hapd);
@@ -167,7 +168,6 @@ struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr)
 
 static void ap_sta_delayed_1x_auth_fail_cb(void *eloop_ctx, void *timeout_ctx)
 {
-	struct hostapd_data *hapd = eloop_ctx;
 	struct sta_info *sta = timeout_ctx;
 	u16 reason;
 
@@ -177,14 +177,21 @@ static void ap_sta_delayed_1x_auth_fail_cb(void *eloop_ctx, void *timeout_ctx)
 
 	reason = WLAN_REASON_IEEE_802_1X_AUTH_FAILED;
 	esp_wifi_ap_deauth_internal(sta->addr, reason);
-	if (sta->flags & WLAN_STA_WPS)
-		hostapd_wps_eap_completed(hapd);
 }
 
 
 void ap_sta_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd,
 					    struct sta_info *sta)
 {
+#ifdef ESP_SUPPLICANT
+	wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
+		"IEEE 802.1X: Scheduled disconnection of " MACSTR
+		" after EAP-Failure", MAC2STR(sta->addr));
+
+	esp_wifi_ap_deauth_internal(sta->addr, WLAN_REASON_IEEE_802_1X_AUTH_FAILED);
+	if (wps_get_status() == WPS_STATUS_PENDING)
+		wps_set_status(WPS_STATUS_DISABLE);
+#else
 	wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
 		"IEEE 802.1X: Force disconnection of " MACSTR
 		" after EAP-Failure in 10 ms", MAC2STR(sta->addr));
@@ -197,6 +204,7 @@ void ap_sta_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd,
 	eloop_cancel_timeout(ap_sta_delayed_1x_auth_fail_cb, hapd, sta);
 	eloop_register_timeout(0, 10000, ap_sta_delayed_1x_auth_fail_cb,
 			       hapd, sta);
+#endif
 }
 
 

+ 30 - 0
components/wpa_supplicant/src/ap/wpa_auth.c

@@ -31,6 +31,7 @@
 #include "esp_wifi.h"
 #include "esp_private/wifi.h"
 #include "esp_wpas_glue.h"
+#include "esp_wps_i.h"
 
 #define STATE_MACHINE_DATA struct wpa_state_machine
 #define STATE_MACHINE_DEBUG_PREFIX "WPA"
@@ -2375,13 +2376,42 @@ bool wpa_ap_join(struct sta_info *sta, uint8_t *bssid, uint8_t *wpa_ie, uint8_t
     return true;
 }
 
+#ifdef CONFIG_WPS_REGISTRAR
+static void ap_free_sta_timeout(void *ctx, void *data)
+{
+    struct hostapd_data *hapd = (struct hostapd_data *) ctx;
+    u8 *addr = (u8 *) data;
+    struct sta_info *sta = ap_get_sta(hapd, addr);
+
+    if (sta) {
+        ap_free_sta(hapd, sta);
+    }
+
+    os_free(addr);
+}
+#endif
+
 bool wpa_ap_remove(void* sta_info)
 {
     struct hostapd_data *hapd = hostapd_get_hapd_data();
+
     if (!sta_info || !hapd) {
         return false;
     }
 
+#ifdef CONFIG_WPS_REGISTRAR
+    wpa_printf(MSG_DEBUG, "wps_status=%d", wps_get_status());
+    if (wps_get_status() == WPS_STATUS_PENDING) {
+        struct sta_info *sta = (struct sta_info *)sta_info;
+        u8 *addr = os_malloc(ETH_ALEN);
+
+	if (!addr) {
+            return false;
+	}
+	os_memcpy(addr, sta->addr, ETH_ALEN);
+        eloop_register_timeout(0, 10000, ap_free_sta_timeout, hapd, addr);
+    } else
+#endif
     ap_free_sta(hapd, sta_info);
 
     return true;

+ 31 - 91
components/wpa_supplicant/src/ap/wps_hostapd.c

@@ -90,7 +90,6 @@ static void hostapd_wps_reg_success_cb(void *ctx, const u8 *mac_addr,
 	data.dev_pw = dev_pw;
 	data.dev_pw_len = dev_pw_len;
 	wps_stop_registrar(hapd, &data);
-        wps_set_status(WPS_STATUS_DISABLE);
 
 	/* TODO add callback event for freeRTOS */
 }
@@ -111,68 +110,20 @@ static void hostapd_wps_reenable_ap_pin(void *eloop_data, void *user_ctx)
 	wps_registrar_update_ie(hapd->wps->registrar);
 }
 
-
-static int wps_pwd_auth_fail(struct hostapd_data *hapd, void *ctx)
-{
-	struct wps_event_pwd_auth_fail *data = ctx;
-
-	if (!data->enrollee || hapd->conf->ap_pin == NULL || hapd->wps == NULL)
-		return 0;
-
-	/*
-	 * Registrar failed to prove its knowledge of the AP PIN. Lock AP setup
-	 * for some time if this happens multiple times to slow down brute
-	 * force attacks.
-	 */
-	hapd->ap_pin_failures++;
-	hapd->ap_pin_failures_consecutive++;
-	wpa_printf(MSG_DEBUG, "WPS: AP PIN authentication failure number %u "
-		   "(%u consecutive)",
-		   hapd->ap_pin_failures, hapd->ap_pin_failures_consecutive);
-	if (hapd->ap_pin_failures < 3)
-		return 0;
-
-	wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_AP_SETUP_LOCKED);
-	hapd->wps->ap_setup_locked = 1;
-
-	wps_registrar_update_ie(hapd->wps->registrar);
-
-	if (!hapd->conf->ap_setup_locked &&
-	    hapd->ap_pin_failures_consecutive >= 10) {
-		/*
-		 * In indefinite lockdown - disable automatic AP PIN
-		 * reenablement.
-		 */
-		eloop_cancel_timeout(hostapd_wps_reenable_ap_pin, hapd, NULL);
-		wpa_printf(MSG_DEBUG, "WPS: AP PIN disabled indefinitely");
-	} else if (!hapd->conf->ap_setup_locked) {
-		if (hapd->ap_pin_lockout_time == 0)
-			hapd->ap_pin_lockout_time = 60;
-		else if (hapd->ap_pin_lockout_time < 365 * 24 * 60 * 60 &&
-			 (hapd->ap_pin_failures % 3) == 0)
-			hapd->ap_pin_lockout_time *= 2;
-
-		wpa_printf(MSG_DEBUG, "WPS: Disable AP PIN for %u seconds",
-			   hapd->ap_pin_lockout_time);
-		eloop_cancel_timeout(hostapd_wps_reenable_ap_pin, hapd, NULL);
-		eloop_register_timeout(hapd->ap_pin_lockout_time, 0,
-				       hostapd_wps_reenable_ap_pin, hapd,
-				       NULL);
-	}
-
-	return 0;
-}
-
-
 static void hostapd_pwd_auth_fail(struct hostapd_data *hapd,
 				  struct wps_event_pwd_auth_fail *data)
 {
 	/* Update WPS Status - Authentication Failure */
+	wifi_event_ap_wps_rg_fail_reason_t evt = {0};
+
 	wpa_printf(MSG_DEBUG, "WPS: Authentication failure update");
 	hapd->wps_stats.status = WPS_FAILURE_STATUS;
 	os_memcpy(hapd->wps_stats.peer_addr, data->peer_macaddr, ETH_ALEN);
 
-	wps_pwd_auth_fail(hapd, data);
+	os_memcpy(evt.peer_macaddr, data->peer_macaddr, ETH_ALEN);
+	evt.reason = WPS_AP_FAIL_REASON_AUTH;
+	esp_event_post(WIFI_EVENT, WIFI_EVENT_AP_WPS_RG_FAILED, &evt,
+			sizeof(evt), OS_BLOCK);
 }
 
 
@@ -193,16 +144,12 @@ static int wps_ap_pin_success(struct hostapd_data *hapd, void *ctx)
 }
 
 
-static void hostapd_wps_ap_pin_success(struct hostapd_data *hapd)
-{
-	wps_ap_pin_success(hapd, NULL);
-}
-
-
 static void hostapd_wps_event_pbc_overlap(struct hostapd_data *hapd)
 {
 	/* Update WPS Status - PBC Overlap */
+
 	hapd->wps_stats.pbc_status = WPS_PBC_STATUS_OVERLAP;
+	esp_event_post(WIFI_EVENT, WIFI_EVENT_AP_WPS_RG_PBC_OVERLAP, NULL, 0, OS_BLOCK);
 }
 
 
@@ -210,16 +157,14 @@ static void hostapd_wps_event_pbc_timeout(struct hostapd_data *hapd)
 {
 	/* Update WPS PBC Status:PBC Timeout */
 	hapd->wps_stats.pbc_status = WPS_PBC_STATUS_TIMEOUT;
+	esp_event_post(WIFI_EVENT, WIFI_EVENT_AP_WPS_RG_TIMEOUT, NULL, 0, OS_BLOCK);
 }
 
-
-static void hostapd_wps_event_pbc_active(struct hostapd_data *hapd)
+static void hostapd_wps_event_pin_timeout(struct hostapd_data *hapd)
 {
-	/* Update WPS PBC status - Active */
-	hapd->wps_stats.pbc_status = WPS_PBC_STATUS_ACTIVE;
+	esp_event_post(WIFI_EVENT, WIFI_EVENT_AP_WPS_RG_TIMEOUT, NULL, 0, OS_BLOCK);
 }
 
-
 static void hostapd_wps_event_pbc_disable(struct hostapd_data *hapd)
 {
 	/* Update WPS PBC status - Active */
@@ -230,31 +175,25 @@ static void hostapd_wps_event_pbc_disable(struct hostapd_data *hapd)
 static void hostapd_wps_event_success(struct hostapd_data *hapd,
 				      struct wps_event_success *success)
 {
-	/* Update WPS status - Success */
-	hapd->wps_stats.pbc_status = WPS_PBC_STATUS_DISABLE;
-	hapd->wps_stats.status = WPS_SUCCESS_STATUS;
-	os_memcpy(hapd->wps_stats.peer_addr, success->peer_macaddr, ETH_ALEN);
+	wifi_event_ap_wps_rg_success_t evt;
+
+	os_memcpy(evt.peer_macaddr, success->peer_macaddr, ETH_ALEN);
+	esp_event_post(WIFI_EVENT, WIFI_EVENT_AP_WPS_RG_SUCCESS, &evt,
+			sizeof(evt), OS_BLOCK);
 }
 
 
 static void hostapd_wps_event_fail(struct hostapd_data *hapd,
 				   struct wps_event_fail *fail)
 {
-	/* Update WPS status - Failure */
-	hapd->wps_stats.status = WPS_FAILURE_STATUS;
-	os_memcpy(hapd->wps_stats.peer_addr, fail->peer_macaddr, ETH_ALEN);
-
-	if (fail->error_indication > 0 &&
-	    fail->error_indication < NUM_WPS_EI_VALUES) {
-		wpa_msg(hapd->msg_ctx, MSG_INFO,
-			WPS_EVENT_FAIL "msg=%d config_error=%d reason=%d (%s)",
-			fail->msg, fail->config_error, fail->error_indication,
-			wps_ei_str(fail->error_indication));
-	} else {
-		wpa_msg(hapd->msg_ctx, MSG_INFO,
-			WPS_EVENT_FAIL "msg=%d config_error=%d",
-			fail->msg, fail->config_error);
-	}
+	wifi_event_ap_wps_rg_fail_reason_t evt;
+	if (fail->config_error > WPS_CFG_NO_ERROR)
+		evt.reason = WPS_AP_FAIL_REASON_CONFIG;
+	else
+		evt.reason = WPS_AP_FAIL_REASON_NORMAL;
+	os_memcpy(evt.peer_macaddr, fail->peer_macaddr, ETH_ALEN);
+	esp_event_post(WIFI_EVENT, WIFI_EVENT_AP_WPS_RG_FAILED, &evt,
+			sizeof(evt), OS_BLOCK);
 }
 
 
@@ -264,9 +203,6 @@ static void hostapd_wps_event_cb(void *ctx, enum wps_event event,
 	struct hostapd_data *hapd = ctx;
 
 	switch (event) {
-	case WPS_EV_M2D:
-		wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_M2D);
-		break;
 	case WPS_EV_FAIL:
 		hostapd_wps_event_fail(hapd, &data->fail);
 		break;
@@ -285,8 +221,9 @@ static void hostapd_wps_event_cb(void *ctx, enum wps_event event,
 		hostapd_wps_event_pbc_timeout(hapd);
 		wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_TIMEOUT);
 		break;
+	case WPS_EV_SELECTED_REGISTRAR_TIMEOUT:
+		hostapd_wps_event_pin_timeout(hapd);
 	case WPS_EV_PBC_ACTIVE:
-		hostapd_wps_event_pbc_active(hapd);
 		wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_ACTIVE);
 		break;
 	case WPS_EV_PBC_DISABLE:
@@ -306,7 +243,9 @@ static void hostapd_wps_event_cb(void *ctx, enum wps_event event,
 	case WPS_EV_ER_SET_SELECTED_REGISTRAR:
 		break;
 	case WPS_EV_AP_PIN_SUCCESS:
-		hostapd_wps_ap_pin_success(hapd);
+		wps_ap_pin_success(hapd, NULL);
+		break;
+	default:
 		break;
 	}
 	if (hapd->wps_event_cb)
@@ -392,7 +331,8 @@ void hostapd_deinit_wps(struct hostapd_data *hapd)
 		return;
 	}
 	wps_registrar_deinit(hapd->wps->registrar);
-	hostapd_free_wps(hapd->wps);
+	hapd->wps->registrar = NULL;
+	eap_server_unregister_methods();
 	hapd->wps = NULL;
 	hostapd_wps_clear_ies(hapd, 1);
 }

+ 1 - 1
components/wpa_supplicant/src/eap_server/eap_server_wsc.c

@@ -101,7 +101,7 @@ static void eap_wsc_reset(struct eap_sm *sm, void *priv)
 	struct eap_wsc_data *data = priv;
 	wpabuf_free(data->in_buf);
 	wpabuf_free(data->out_buf);
-	wps_deinit(data->wps);
+	//wps_deinit(data->wps);
 	os_free(data);
 }
 

+ 3 - 1
components/wpa_supplicant/src/wps/wps.h

@@ -521,7 +521,9 @@ enum wps_event {
 	/**
 	 * WPS_EV_AP_PIN_SUCCESS - External Registrar used correct AP PIN
 	 */
-	WPS_EV_AP_PIN_SUCCESS
+	WPS_EV_AP_PIN_SUCCESS,
+
+	WPS_EV_SELECTED_REGISTRAR_TIMEOUT,
 };
 
 /**

+ 8 - 0
components/wpa_supplicant/src/wps/wps_common.c

@@ -330,6 +330,14 @@ void wps_pbc_overlap_event(struct wps_context *wps)
 }
 
 
+void wps_selected_registrar_timeout_event(struct wps_context *wps)
+{
+	if (wps->event_cb == NULL)
+		return;
+
+	wps->event_cb(wps->cb_ctx, WPS_EV_SELECTED_REGISTRAR_TIMEOUT, NULL);
+}
+
 void wps_pbc_timeout_event(struct wps_context *wps)
 {
 	if (wps->event_cb == NULL)

+ 1 - 0
components/wpa_supplicant/src/wps/wps_i.h

@@ -145,6 +145,7 @@ void wps_success_event(struct wps_context *wps, const u8 *mac_addr);
 void wps_pwd_auth_fail_event(struct wps_context *wps, int enrollee, int part,
 			     const u8 *mac_addr);
 void wps_pbc_overlap_event(struct wps_context *wps);
+void wps_selected_registrar_timeout_event(struct wps_context *wps);
 void wps_pbc_timeout_event(struct wps_context *wps);
 void wps_pbc_active_event(struct wps_context *wps);
 void wps_pbc_disable_event(struct wps_context *wps);

+ 1 - 1
components/wpa_supplicant/src/wps/wps_registrar.c

@@ -852,7 +852,6 @@ static void wps_registrar_remove_pin(struct wps_registrar *reg,
 		addr = pin->enrollee_addr;
 	wps_registrar_remove_authorized_mac(reg, addr);
 	wps_remove_pin(pin);
-	wps_registrar_selected_registrar_changed(reg, 0);
 }
 
 
@@ -3485,6 +3484,7 @@ static void wps_registrar_set_selected_timeout(void *eloop_ctx,
 	reg->pbc = 0;
 	wps_registrar_expire_pins(reg);
 	wps_registrar_selected_registrar_changed(reg, 0);
+	wps_selected_registrar_timeout_event(reg->wps);
 }
 
 

+ 6 - 0
examples/wifi/wps_softap_registrar/CMakeLists.txt

@@ -0,0 +1,6 @@
+# The following lines of boilerplate have to be in your project's CMakeLists
+# in this exact order for cmake to work correctly
+cmake_minimum_required(VERSION 3.16)
+
+include($ENV{IDF_PATH}/tools/cmake/project.cmake)
+project(wps_softap_registrar)

+ 53 - 0
examples/wifi/wps_softap_registrar/README.md

@@ -0,0 +1,53 @@
+| Supported Targets | ESP32 | ESP32-C3 | ESP32-S2 | ESP32-S3 |
+| ----------------- | ----- | -------- | -------- | -------- |
+
+# Wi-Fi WPS Registrar Example
+
+(See the README.md file in the upper level 'examples' directory for more information about examples.)
+
+This example shows how to use WPS registrar sotAP mode in ESP. The WPS protocol simplifies the process of connecting to a Wi-Fi softAP from a station.
+
+## How to use example
+
+Before project configuration and build, be sure to set the correct chip target using `idf.py set-target <chip_name>`.
+
+### Hardware Required
+
+* A development board with ESP32/ESP32-S2/ESP32-C3/ESP32-S3 SoC (e.g., ESP32-DevKitC, ESP-WROVER-KIT, etc.)
+* A USB cable for Power supply and programming
+
+### Configure the project
+
+Open the project configuration menu (`idf.py menuconfig`).
+
+In the `Example Configuration` menu:
+
+* Use `WPS mode` to select the type.
+* Select `PBC`, `PIN` or `disable`.
+
+In `PBC` mode, the ESP will wait for the WPS initialization (usually by pressing WPS button on the Wi-Fi station).
+
+In `PIN` mode, the ESP will enter the WPS mode and you'll see a pin code on the terminal(If not given through user config). Enter this pin code in your station and then the ESP will connect to it.
+
+(See your station's manual and configuration for WPS compatibility.)
+
+### Build and Flash
+
+Build the project and flash it to the board, then run the monitor tool to view the serial output:
+
+Run `idf.py -p PORT flash monitor` to build, flash and monitor the project.
+
+(To exit the serial monitor, type ``Ctrl-]``.)
+
+See the Getting Started Guide for all the steps to configure and use the ESP-IDF to build projects.
+
+* [ESP-IDF Getting Started Guide on ESP32](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/index.html)
+* [ESP-IDF Getting Started Guide on ESP32-S2](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/get-started/index.html)
+* [ESP-IDF Getting Started Guide on ESP32-C3](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/get-started/index.html)
+* [ESP-IDF Getting Started Guide on ESP32-S3](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/get-started/index.html)
+* [ESP-IDF Getting Started Guide on ESP32-C2](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c2/get-started/index.html)
+
+
+## Troubleshooting
+
+For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon.

+ 2 - 0
examples/wifi/wps_softap_registrar/main/CMakeLists.txt

@@ -0,0 +1,2 @@
+idf_component_register(SRCS "wps.c"
+                    INCLUDE_DIRS ".")

+ 50 - 0
examples/wifi/wps_softap_registrar/main/Kconfig.projbuild

@@ -0,0 +1,50 @@
+menu "Example Configuration"
+
+    config EXAMPLE_WIFI_SSID
+        string "WiFi SSID"
+        default "myssid"
+        help
+            SSID (network name) for the example to connect to.
+
+    config EXAMPLE_WIFI_PASSWORD
+        string "WiFi Password"
+        default "mypassword"
+        help
+            WiFi password (WPA or WPA2) for the example to use.
+
+    config EXAMPLE_WIFI_CHANNEL
+        int "WiFi Channel"
+        range 1 13
+        default 1
+        help
+            WiFi channel (network channel) for the example to use.
+
+    config EXAMPLE_MAX_STA_CONN
+        int "Maximal STA connections"
+        default 4
+        help
+            Max number of the STA connects to AP.
+
+    choice EXAMPLE_WPS_TYPE
+        prompt "WPS mode"
+        default EXAMPLE_WPS_TYPE_PBC
+        help
+            WPS type for the esp32 to use.
+
+        config EXAMPLE_WPS_TYPE_PBC
+            bool "PBC"
+        config EXAMPLE_WPS_TYPE_PIN
+            bool "PIN"
+        config EXAMPLE_WPS_TYPE_DISABLE
+            bool "disable"
+    endchoice
+
+    if EXAMPLE_WPS_TYPE_PIN
+        config EXAMPLE_WPS_PIN_VALUE
+            int "WPS PIN"
+            default 0
+            help
+                WPS PIN to be used for the connection, incase its not give, AP will derive a new one.
+    endif
+
+endmenu

+ 179 - 0
examples/wifi/wps_softap_registrar/main/wps.c

@@ -0,0 +1,179 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Unlicense OR CC0-1.0
+ */
+/* WPS Registrar example in softAP mode
+
+   This example code is in the Public Domain (or CC0 licensed, at your option.)
+
+   Unless required by applicable law or agreed to in writing, this
+   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+   CONDITIONS OF ANY KIND, either express or implied.
+*/
+
+#include "freertos/FreeRTOS.h"
+#include "freertos/event_groups.h"
+#include "esp_wifi.h"
+#include "esp_mac.h"
+#include "esp_log.h"
+#include "esp_wps.h"
+#include "esp_event.h"
+#include "nvs_flash.h"
+#include <string.h>
+
+
+/*set wps mode via project configuration */
+#if CONFIG_EXAMPLE_WPS_TYPE_PBC
+#define WPS_MODE WPS_TYPE_PBC
+#elif CONFIG_EXAMPLE_WPS_TYPE_PIN
+#if CONFIG_EXAMPLE_WPS_PIN_VALUE
+#define EXAMPLE_WPS_PIN_VALUE CONFIG_EXAMPLE_WPS_PIN_VALUE
+#endif
+#define WPS_MODE WPS_TYPE_PIN
+#else
+#define WPS_MODE WPS_TYPE_DISABLE
+#endif /*CONFIG_EXAMPLE_WPS_TYPE_PBC*/
+
+
+#ifndef PIN2STR
+#define PIN2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5], (a)[6], (a)[7]
+#define PINSTR "%c%c%c%c%c%c%c%c"
+#endif
+
+#define EXAMPLE_ESP_WIFI_SSID      CONFIG_EXAMPLE_WIFI_SSID
+#define EXAMPLE_ESP_WIFI_PASS      CONFIG_EXAMPLE_WIFI_PASSWORD
+#define EXAMPLE_ESP_WIFI_CHANNEL   CONFIG_EXAMPLE_WIFI_CHANNEL
+#define EXAMPLE_MAX_STA_CONN       CONFIG_EXAMPLE_MAX_STA_CONN
+
+static const char *TAG = "example_wps_registrar";
+static esp_wps_config_t config = WPS_CONFIG_INIT_DEFAULT(WPS_MODE);
+
+static unsigned char pin[9];
+
+static void wifi_event_handler(void* arg, esp_event_base_t event_base,
+		int32_t event_id, void* event_data)
+{
+	switch (event_id) {
+	case WIFI_EVENT_AP_START:
+		ESP_LOGI(TAG, "WIFI_EVENT_AP_START");
+		break;
+	case WIFI_EVENT_AP_STADISCONNECTED:
+		{
+			ESP_LOGI(TAG, "WIFI_EVENT_AP_STADISCONNECTED");
+			wifi_event_ap_stadisconnected_t* event = (wifi_event_ap_stadisconnected_t*) event_data;
+			ESP_LOGI(TAG, "station "MACSTR" leave, AID=%d",
+					MAC2STR(event->mac), event->aid);
+		}
+		break;
+	case WIFI_EVENT_AP_STACONNECTED:
+		{
+			ESP_LOGI(TAG, "WIFI_EVENT_AP_STACONNECTED");
+			wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) event_data;
+			ESP_LOGI(TAG, "station "MACSTR" join, AID=%d",
+					MAC2STR(event->mac), event->aid);
+		}
+		break;
+	case WIFI_EVENT_AP_WPS_RG_SUCCESS:
+		{
+			ESP_LOGI(TAG, "WIFI_EVENT_AP_WPS_RG_SUCCESS");
+			wifi_event_ap_wps_rg_success_t *evt = (wifi_event_ap_wps_rg_success_t *)event_data;
+			ESP_LOGI(TAG, "station "MACSTR" WPS successful",
+					MAC2STR(evt->peer_macaddr));
+		}
+		break;
+	case WIFI_EVENT_AP_WPS_RG_FAILED:
+		{
+			ESP_LOGI(TAG, "WIFI_EVENT_AP_WPS_RG_FAILED");
+			wifi_event_ap_wps_rg_fail_reason_t *evt = (wifi_event_ap_wps_rg_fail_reason_t *)event_data;
+			ESP_LOGI(TAG, "station "MACSTR" WPS failed, reason=%d",
+						MAC2STR(evt->peer_macaddr), evt->reason);
+			ESP_ERROR_CHECK(esp_wifi_ap_wps_disable());
+			ESP_ERROR_CHECK(esp_wifi_ap_wps_enable(&config));
+			ESP_ERROR_CHECK(esp_wifi_ap_wps_start(pin));
+		}
+		break;
+	case WIFI_EVENT_AP_WPS_RG_TIMEOUT:
+		{
+			ESP_LOGI(TAG, "WIFI_EVENT_AP_WPS_RG_TIMEOUT");
+			ESP_ERROR_CHECK(esp_wifi_ap_wps_disable());
+			ESP_ERROR_CHECK(esp_wifi_ap_wps_enable(&config));
+			ESP_ERROR_CHECK(esp_wifi_ap_wps_start(pin));
+		}
+		break;
+	case WIFI_EVENT_AP_WPS_RG_PIN:
+		{
+			ESP_LOGI(TAG, "WIFI_EVENT_AP_WPS_RG_PIN");
+			/* display the PIN code */
+			wifi_event_ap_wps_rg_pin_t* event = (wifi_event_ap_wps_rg_pin_t *) event_data;
+			ESP_LOGI(TAG, "WPS_PIN = " PINSTR, PIN2STR(event->pin_code));
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+/*init wifi as sta and start wps*/
+static void start_wps_registrar(void)
+{
+	ESP_ERROR_CHECK(esp_netif_init());
+	ESP_ERROR_CHECK(esp_event_loop_create_default());
+	esp_netif_create_default_wifi_ap();
+
+	wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
+	ESP_ERROR_CHECK(esp_wifi_init(&cfg));
+
+	ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL));
+
+	wifi_config_t wifi_config = {
+		.ap = {
+			.ssid = EXAMPLE_ESP_WIFI_SSID,
+			.ssid_len = strlen(EXAMPLE_ESP_WIFI_SSID),
+			.channel = EXAMPLE_ESP_WIFI_CHANNEL,
+			.password = EXAMPLE_ESP_WIFI_PASS,
+			.max_connection = EXAMPLE_MAX_STA_CONN,
+			.authmode = WIFI_AUTH_WPA2_PSK,
+			.pmf_cfg = {
+				.required = false,
+			},
+		},
+	};
+	if (strlen(EXAMPLE_ESP_WIFI_PASS) == 0) {
+		wifi_config.ap.authmode = WIFI_AUTH_OPEN;
+	}
+
+	ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
+	ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config));
+
+	ESP_ERROR_CHECK(esp_wifi_start());
+
+	ESP_LOGI(TAG, "start wps...");
+
+	ESP_ERROR_CHECK(esp_wifi_ap_wps_enable(&config));
+#if EXAMPLE_WPS_PIN_VALUE
+	ESP_LOGI(TAG, "Staring WPS registrar with user specified pin %s", pin);
+	snprintf((char *)pin, 9, "%08d", EXAMPLE_WPS_PIN_VALUE);
+	ESP_ERROR_CHECK(esp_wifi_ap_wps_start(pin));
+#else
+	if (config.wps_type == WPS_TYPE_PBC) {
+		ESP_LOGI(TAG, "Staring WPS registrar in PBC mode");
+	} else {
+		ESP_LOGI(TAG, "Staring WPS registrar with random generated pin");
+	}
+	ESP_ERROR_CHECK(esp_wifi_ap_wps_start(NULL));
+#endif
+}
+
+void app_main(void)
+{
+	/* Initialize NVS — it is used to store PHY calibration data */
+	esp_err_t ret = nvs_flash_init();
+	if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
+		ESP_ERROR_CHECK(nvs_flash_erase());
+		ret = nvs_flash_init();
+	}
+	ESP_ERROR_CHECK( ret );
+
+	start_wps_registrar();
+}

+ 2 - 0
examples/wifi/wps_softap_registrar/sdkconfig.defaults

@@ -0,0 +1,2 @@
+CONFIG_ESP_WIFI_SOFTAP_SUPPORT=y
+CONFIG_WPA_WPS_SOFTAP_REGISTRAR=y